Merge "Cancel startAnimation(show=true) if IME is not requested to be visible" into main
diff --git a/OWNERS b/OWNERS
index bde7ab2..096da29 100644
--- a/OWNERS
+++ b/OWNERS
@@ -14,6 +14,7 @@
nandana@google.com #{LAST_RESORT_SUGGESTION}
narayan@google.com #{LAST_RESORT_SUGGESTION}
ogunwale@google.com #{LAST_RESORT_SUGGESTION}
+omakoto@google.com #{LAST_RESORT_SUGGESTION}
roosa@google.com #{LAST_RESORT_SUGGESTION}
smoreland@google.com #{LAST_RESORT_SUGGESTION}
yamasani@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java
index 2643bae..d7b1c9a2 100644
--- a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java
+++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java
@@ -43,6 +43,7 @@
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -196,6 +197,7 @@
*/
@Test
@Parameters(method = "getParams")
+ @Ignore("b/351034205")
public void time(Config config) throws Exception {
reset();
setup(config);
diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java
index 4f285ff..8916a3c 100644
--- a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java
+++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java
@@ -43,6 +43,7 @@
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -201,6 +202,7 @@
@Test
@Parameters(method = "getParams")
+ @Ignore("b/351034205")
public void throughput(Config config) throws Exception {
setup(config);
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index 9a178e5..18ee6f2 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -165,6 +165,7 @@
import com.android.server.SystemServiceManager;
import com.android.server.SystemTimeZone;
import com.android.server.SystemTimeZone.TimeZoneConfidence;
+import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.permission.PermissionManagerService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.pm.pkg.AndroidPackage;
@@ -3763,8 +3764,10 @@
}
mNextAlarmClockForUser.put(userId, alarmClock);
if (mStartUserBeforeScheduledAlarms) {
- mUserWakeupStore.addUserWakeup(userId, convertToElapsed(
- mNextAlarmClockForUser.get(userId).getTriggerTime(), RTC));
+ if (shouldAddWakeupForUser(userId)) {
+ mUserWakeupStore.addUserWakeup(userId, convertToElapsed(
+ mNextAlarmClockForUser.get(userId).getTriggerTime(), RTC));
+ }
}
} else {
if (DEBUG_ALARM_CLOCK) {
@@ -3784,6 +3787,23 @@
}
/**
+ * Checks whether the user is of type that needs to be started before the alarm.
+ */
+ @VisibleForTesting
+ boolean shouldAddWakeupForUser(@UserIdInt int userId) {
+ final UserManagerInternal umInternal = LocalServices.getService(UserManagerInternal.class);
+ if (umInternal.getUserInfo(userId) == null || umInternal.getUserInfo(userId).isGuest()) {
+ // Guest user should not be started in the background.
+ return false;
+ } else {
+ // SYSTEM user is always running, so no need to schedule wakeup for it.
+ // Profiles are excluded from the wakeup list because users can explicitly stop them and
+ // so starting them in the background would go against the user's intent.
+ return userId != UserHandle.USER_SYSTEM && umInternal.getUserInfo(userId).isFull();
+ }
+ }
+
+ /**
* Updates NEXT_ALARM_FORMATTED and sends NEXT_ALARM_CLOCK_CHANGED_INTENT for all users
* for which alarm clocks have changed since the last call to this.
*
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/UserWakeupStore.java b/apex/jobscheduler/service/java/com/android/server/alarm/UserWakeupStore.java
index 93904a7..9fe197d 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/UserWakeupStore.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/UserWakeupStore.java
@@ -20,7 +20,6 @@
import android.annotation.Nullable;
import android.os.Environment;
import android.os.SystemClock;
-import android.os.UserHandle;
import android.util.AtomicFile;
import android.util.IndentingPrintWriter;
import android.util.Pair;
@@ -119,13 +118,10 @@
* @param alarmTime time when alarm is expected to trigger.
*/
public void addUserWakeup(int userId, long alarmTime) {
- // SYSTEM user is always running, so no need to schedule wakeup for it.
- if (userId != UserHandle.USER_SYSTEM) {
- synchronized (mUserWakeupLock) {
- mUserStarts.put(userId, alarmTime - BUFFER_TIME_MS + getUserWakeupOffset());
- }
- updateUserListFile();
+ synchronized (mUserWakeupLock) {
+ mUserStarts.put(userId, alarmTime - BUFFER_TIME_MS + getUserWakeupOffset());
}
+ updateUserListFile();
}
/**
diff --git a/core/api/current.txt b/core/api/current.txt
index c5a70df..354e26b 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -43729,6 +43729,7 @@
field public static final String KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY = "carrier_nr_availabilities_int_array";
field public static final String KEY_CARRIER_PROVISIONS_WIFI_MERGED_NETWORKS_BOOL = "carrier_provisions_wifi_merged_networks_bool";
field public static final String KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL = "carrier_rcs_provisioning_required_bool";
+ field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT = "carrier_roaming_ntn_emergency_call_to_satellite_handover_type_int";
field public static final String KEY_CARRIER_SERVICE_NAME_STRING_ARRAY = "carrier_service_name_array";
field public static final String KEY_CARRIER_SERVICE_NUMBER_STRING_ARRAY = "carrier_service_number_array";
field public static final String KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING = "carrier_settings_activity_component_name_string";
@@ -43911,6 +43912,7 @@
field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_SATELLITE_ENTITLEMENT_STATUS_REFRESH_DAYS_INT = "satellite_entitlement_status_refresh_days_int";
field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL = "satellite_entitlement_supported_bool";
field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ESOS_SUPPORTED_BOOL = "satellite_esos_supported_bool";
+ field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT = "satellite_screen_off_inactivity_timeout_duration_sec_int";
field public static final String KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL = "show_4g_for_3g_data_icon_bool";
field public static final String KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL = "show_4g_for_lte_data_icon_bool";
field public static final String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index e148b5c..df707d1 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -321,7 +321,7 @@
package android.net.wifi {
public final class WifiMigration {
- method @FlaggedApi("android.net.wifi.flags.legacy_keystore_to_wifi_blobstore_migration") public static void migrateLegacyKeystoreToWifiBlobstore();
+ method @FlaggedApi("android.net.wifi.flags.legacy_keystore_to_wifi_blobstore_migration_read_only") public static void migrateLegacyKeystoreToWifiBlobstore();
}
}
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 7674246..15e5706 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -3448,7 +3448,7 @@
}
public static interface VirtualDeviceManager.ActivityListener {
- method @FlaggedApi("android.companion.virtualdevice.flags.activity_control_api") public default void onActivityLaunchBlocked(int, @NonNull android.content.ComponentName, int);
+ method @FlaggedApi("android.companion.virtualdevice.flags.activity_control_api") public default void onActivityLaunchBlocked(int, @NonNull android.content.ComponentName, int, @Nullable android.content.IntentSender);
method public void onDisplayEmpty(int);
method @Deprecated public void onTopActivityChanged(int, @NonNull android.content.ComponentName);
method public default void onTopActivityChanged(int, @NonNull android.content.ComponentName, int);
@@ -3465,6 +3465,7 @@
public static class VirtualDeviceManager.VirtualDevice implements java.lang.AutoCloseable {
method public void addActivityListener(@NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.ActivityListener);
method @FlaggedApi("android.companion.virtual.flags.dynamic_policy") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void addActivityPolicyExemption(@NonNull android.content.ComponentName);
+ method @FlaggedApi("android.companion.virtualdevice.flags.activity_control_api") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void addActivityPolicyExemption(@NonNull android.content.ComponentName, int);
method public void addSoundEffectListener(@NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.SoundEffectListener);
method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void close();
method @NonNull public android.content.Context createContext();
@@ -3489,8 +3490,10 @@
method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void registerIntentInterceptor(@NonNull android.content.IntentFilter, @NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.IntentInterceptorCallback);
method public void removeActivityListener(@NonNull android.companion.virtual.VirtualDeviceManager.ActivityListener);
method @FlaggedApi("android.companion.virtual.flags.dynamic_policy") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void removeActivityPolicyExemption(@NonNull android.content.ComponentName);
+ method @FlaggedApi("android.companion.virtualdevice.flags.activity_control_api") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void removeActivityPolicyExemption(@NonNull android.content.ComponentName, int);
method public void removeSoundEffectListener(@NonNull android.companion.virtual.VirtualDeviceManager.SoundEffectListener);
method @FlaggedApi("android.companion.virtual.flags.dynamic_policy") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setDevicePolicy(int, int);
+ method @FlaggedApi("android.companion.virtualdevice.flags.activity_control_api") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setDevicePolicy(int, int, int);
method @FlaggedApi("android.companion.virtual.flags.vdm_custom_ime") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setDisplayImePolicy(int, int);
method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setShowPointerIcon(boolean);
method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void unregisterIntentInterceptor(@NonNull android.companion.virtual.VirtualDeviceManager.IntentInterceptorCallback);
@@ -6718,14 +6721,6 @@
field public static final int STATUS_OK = 0; // 0x0
}
- @FlaggedApi("android.media.soundtrigger.sound_trigger_generic_model_api") public static final class SoundTrigger.GenericSoundModel extends android.hardware.soundtrigger.SoundTrigger.SoundModel implements android.os.Parcelable {
- ctor public SoundTrigger.GenericSoundModel(@NonNull java.util.UUID, @NonNull java.util.UUID, @Nullable byte[], int);
- ctor public SoundTrigger.GenericSoundModel(@NonNull java.util.UUID, @NonNull java.util.UUID, @Nullable byte[]);
- method public int describeContents();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.SoundTrigger.GenericSoundModel> CREATOR;
- }
-
public static final class SoundTrigger.Keyphrase implements android.os.Parcelable {
ctor public SoundTrigger.Keyphrase(int, int, @NonNull java.util.Locale, @NonNull String, @Nullable int[]);
method public int describeContents();
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 128fb62..92bca3c 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -22,11 +22,9 @@
":framework-nfc-non-updatable-sources",
":messagequeue-gen",
],
- // Exactly one of the below will be added to srcs by messagequeue-gen
+ // Exactly one MessageQueue.java will be added to srcs by messagequeue-gen
exclude_srcs: [
- "android/os/LegacyMessageQueue/MessageQueue.java",
- "android/os/ConcurrentMessageQueue/MessageQueue.java",
- "android/os/SemiConcurrentMessageQueue/MessageQueue.java",
+ "android/os/*MessageQueue/**/*.java",
],
visibility: ["//frameworks/base"],
}
diff --git a/core/java/android/app/ActivityClient.java b/core/java/android/app/ActivityClient.java
index 10dc3c6..62aa5e0 100644
--- a/core/java/android/app/ActivityClient.java
+++ b/core/java/android/app/ActivityClient.java
@@ -25,7 +25,6 @@
import android.content.ContentProvider;
import android.content.Intent;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
@@ -660,28 +659,6 @@
}
}
- /**
- * Shows or hides a Camera app compat toggle for stretched issues with the requested state.
- *
- * @param token The token for the window that needs a control.
- * @param showControl Whether the control should be shown or hidden.
- * @param transformationApplied Whether the treatment is already applied.
- * @param callback The callback executed when the user clicks on a control.
- */
- void requestCompatCameraControl(Resources res, IBinder token, boolean showControl,
- boolean transformationApplied, ICompatCameraControlCallback callback) {
- if (!res.getBoolean(com.android.internal.R.bool
- .config_isCameraCompatControlForStretchedIssuesEnabled)) {
- return;
- }
- try {
- getActivityClientController().requestCompatCameraControl(
- token, showControl, transformationApplied, callback);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- }
-
public static ActivityClient getInstance() {
return sInstance.get();
}
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 83c3bf6..89efa9b 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -55,6 +55,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.Executor;
import java.util.function.BiFunction;
/**
@@ -1268,6 +1269,28 @@
public abstract boolean shouldDelayHomeLaunch(int userId);
/**
+ * Used to track when a process is frozen or unfrozen.
+ */
+ public interface FrozenProcessListener {
+ /**
+ * Called when a process is frozen.
+ */
+ void onProcessFrozen(int pid);
+
+ /**
+ * Called when a process is unfrozen.
+ */
+ void onProcessUnfrozen(int pid);
+ }
+
+ /**
+ * Register the frozen process event listener callback. The same listener may be reused for
+ * multiple pids. Listeners are dropped when the process dies.
+ */
+ public abstract void addFrozenProcessListener(int pid, @NonNull Executor executor,
+ @NonNull FrozenProcessListener listener);
+
+ /**
* Add a startup timestamp to the most recent start of the specified process.
*
* @param key The {@link ApplicationStartInfo} start timestamp key of the timestamp to add.
diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java
index c8ab260..799df1f 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -172,7 +172,7 @@
}
}
- /** Removes root tasks of the activity types from the system. */
+ /** Removes root tasks of the activity types from the Default TDA of all displays. */
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
public void removeRootTasksWithActivityTypes(@NonNull int[] activityTypes) {
try {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 75aab7d..d455853 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -232,6 +232,7 @@
import com.android.internal.content.ReferrerIntent;
import com.android.internal.os.BinderCallsStats;
import com.android.internal.os.BinderInternal;
+import com.android.internal.os.DebugStore;
import com.android.internal.os.RuntimeInit;
import com.android.internal.os.SafeZipPathValidatorCallback;
import com.android.internal.os.SomeArgs;
@@ -358,6 +359,15 @@
private static final long BINDER_CALLBACK_THROTTLE = 10_100L;
private long mBinderCallbackLast = -1;
+ private static final boolean DEBUG_STORE_ENABLED =
+ com.android.internal.os.Flags.debugStoreEnabled();
+
+ /**
+ * Threshold for identifying long-running looper messages (in milliseconds).
+ * Calculated as 2 seconds multiplied by the hardware timeout multiplier.
+ */
+ private static final long LONG_MESSAGE_THRESHOLD_MS = 2000 * Build.HW_TIMEOUT_MULTIPLIER;
+
/**
* Denotes the sequence number of the process state change for which the main thread needs
* to block until the network rules are updated for it.
@@ -734,19 +744,6 @@
activityWindowInfo,
false /* alwaysReportChange */);
}
-
- @Override
- public void requestCompatCameraControl(boolean showControl,
- boolean transformationApplied, ICompatCameraControlCallback callback) {
- if (activity == null) {
- throw new IllegalStateException(
- "Received camera compat control update for non-existing activity");
- }
- ActivityClient.getInstance().requestCompatCameraControl(
- activity.getResources(), token, showControl, transformationApplied,
- callback);
- }
-
};
}
@@ -2408,6 +2405,12 @@
}
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
+ long debugStoreId = -1;
+ // By default, log all long messages when the debug store is enabled,
+ // unless this is overridden for certain message types, for which we have
+ // more granular debug store logging.
+ boolean shouldLogLongMessage = DEBUG_STORE_ENABLED;
+ final long messageStartUptimeMs = SystemClock.uptimeMillis();
switch (msg.what) {
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
@@ -2432,24 +2435,61 @@
"broadcastReceiveComp");
}
}
- handleReceiver((ReceiverData)msg.obj);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ ReceiverData receiverData = (ReceiverData) msg.obj;
+ if (DEBUG_STORE_ENABLED) {
+ debugStoreId =
+ DebugStore.recordBroadcastHandleReceiver(receiverData.intent);
+ }
+
+ try {
+ handleReceiver(receiverData);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ if (DEBUG_STORE_ENABLED) {
+ DebugStore.recordEventEnd(debugStoreId);
+ shouldLogLongMessage = false;
+ }
+ }
break;
case CREATE_SERVICE:
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
("serviceCreate: " + String.valueOf(msg.obj)));
}
- handleCreateService((CreateServiceData)msg.obj);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ CreateServiceData createServiceData = (CreateServiceData) msg.obj;
+ if (DEBUG_STORE_ENABLED) {
+ debugStoreId = DebugStore.recordServiceCreate(createServiceData.info);
+ }
+
+ try {
+ handleCreateService(createServiceData);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ if (DEBUG_STORE_ENABLED) {
+ DebugStore.recordEventEnd(debugStoreId);
+ shouldLogLongMessage = false;
+ }
+ }
break;
case BIND_SERVICE:
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind: "
+ String.valueOf(msg.obj));
}
- handleBindService((BindServiceData)msg.obj);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ BindServiceData bindData = (BindServiceData) msg.obj;
+ if (DEBUG_STORE_ENABLED) {
+ debugStoreId =
+ DebugStore.recordServiceBind(bindData.rebind, bindData.intent);
+ }
+ try {
+ handleBindService(bindData);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ if (DEBUG_STORE_ENABLED) {
+ DebugStore.recordEventEnd(debugStoreId);
+ shouldLogLongMessage = false;
+ }
+ }
break;
case UNBIND_SERVICE:
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
@@ -2465,8 +2505,21 @@
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
("serviceStart: " + String.valueOf(msg.obj)));
}
- handleServiceArgs((ServiceArgsData)msg.obj);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ ServiceArgsData serviceData = (ServiceArgsData) msg.obj;
+ if (DEBUG_STORE_ENABLED) {
+ debugStoreId = DebugStore.recordServiceOnStart(serviceData.startId,
+ serviceData.flags, serviceData.args);
+ }
+
+ try {
+ handleServiceArgs(serviceData);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ if (DEBUG_STORE_ENABLED) {
+ DebugStore.recordEventEnd(debugStoreId);
+ shouldLogLongMessage = false;
+ }
+ }
break;
case STOP_SERVICE:
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
@@ -2662,11 +2715,17 @@
handleFinishInstrumentationWithoutRestart();
break;
}
+ long messageElapsedTimeMs = SystemClock.uptimeMillis() - messageStartUptimeMs;
Object obj = msg.obj;
if (obj instanceof SomeArgs) {
((SomeArgs) obj).recycle();
}
if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
+ if (shouldLogLongMessage
+ && messageElapsedTimeMs > LONG_MESSAGE_THRESHOLD_MS) {
+ DebugStore.recordLongLooperMessage(msg.what, msg.getTarget().getClass().getName(),
+ messageElapsedTimeMs);
+ }
}
}
@@ -7079,9 +7138,6 @@
&& level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
return;
}
- if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
- PropertyInvalidatedCache.onTrimMemory();
- }
final ArrayList<ComponentCallbacks2> callbacks =
collectComponentCallbacks(true /* includeUiContexts */);
diff --git a/core/java/android/app/AppCompatTaskInfo.java b/core/java/android/app/AppCompatTaskInfo.java
index 92543b1..a6d3f9d 100644
--- a/core/java/android/app/AppCompatTaskInfo.java
+++ b/core/java/android/app/AppCompatTaskInfo.java
@@ -16,6 +16,8 @@
package android.app;
+import static android.app.TaskInfo.PROPERTY_VALUE_UNSET;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
@@ -32,7 +34,7 @@
public boolean topActivityEligibleForLetterboxEducation;
/**
- * Whether the letterbox education is enabled
+ * Whether the letterbox education is enabled.
*/
public boolean isLetterboxEducationEnabled;
@@ -73,28 +75,40 @@
public boolean isFromLetterboxDoubleTap;
/**
- * If {@link isLetterboxDoubleTapEnabled} it contains the current letterbox vertical position or
- * {@link TaskInfo.PROPERTY_VALUE_UNSET} otherwise.
+ * If {@link #isLetterboxDoubleTapEnabled} it contains the current letterbox vertical position
+ * or {@link TaskInfo#PROPERTY_VALUE_UNSET} otherwise.
*/
- public int topActivityLetterboxVerticalPosition;
+ public int topActivityLetterboxVerticalPosition = PROPERTY_VALUE_UNSET;
/**
- * If {@link isLetterboxDoubleTapEnabled} it contains the current letterbox vertical position or
- * {@link TaskInfo.PROPERTY_VALUE_UNSET} otherwise.
+ * If {@link #isLetterboxDoubleTapEnabled} it contains the current letterbox vertical position
+ * or {@link TaskInfo#PROPERTY_VALUE_UNSET} otherwise.
*/
- public int topActivityLetterboxHorizontalPosition;
+ public int topActivityLetterboxHorizontalPosition = PROPERTY_VALUE_UNSET;
/**
- * If {@link isLetterboxDoubleTapEnabled} it contains the current width of the letterboxed
- * activity or {@link TaskInfo.PROPERTY_VALUE_UNSET} otherwise.
+ * If {@link #isLetterboxDoubleTapEnabled} it contains the current width of the letterboxed
+ * activity or {@link TaskInfo#PROPERTY_VALUE_UNSET} otherwise.
*/
- public int topActivityLetterboxWidth;
+ public int topActivityLetterboxWidth = PROPERTY_VALUE_UNSET;
/**
- * If {@link isLetterboxDoubleTapEnabled} it contains the current height of the letterboxed
- * activity or {@link TaskInfo.PROPERTY_VALUE_UNSET} otherwise.
+ * If {@link #isLetterboxDoubleTapEnabled} it contains the current height of the letterboxed
+ * activity or {@link TaskInfo#PROPERTY_VALUE_UNSET} otherwise.
*/
- public int topActivityLetterboxHeight;
+ public int topActivityLetterboxHeight = PROPERTY_VALUE_UNSET;
+
+ /**
+ * Contains the current app height of the letterboxed activity if available or
+ * {@link TaskInfo#PROPERTY_VALUE_UNSET} otherwise.
+ */
+ public int topActivityLetterboxAppHeight = PROPERTY_VALUE_UNSET;
+
+ /**
+ * Contains the current app width of the letterboxed activity if available or
+ * {@link TaskInfo#PROPERTY_VALUE_UNSET} otherwise.
+ */
+ public int topActivityLetterboxAppWidth = PROPERTY_VALUE_UNSET;
/**
* Stores camera-related app compat information about a particular Task.
@@ -133,24 +147,23 @@
};
/**
- * @return {@value true} if the task has some compat ui.
+ * @return {@code true} if the task has some compat ui.
*/
public boolean hasCompatUI() {
- return cameraCompatTaskInfo.hasCameraCompatUI() || topActivityInSizeCompat
- || topActivityEligibleForLetterboxEducation
+ return topActivityInSizeCompat || topActivityEligibleForLetterboxEducation
|| isLetterboxDoubleTapEnabled
|| topActivityEligibleForUserAspectRatioButton;
}
/**
- * @return {@value true} if top activity is pillarboxed.
+ * @return {@code true} if top activity is pillarboxed.
*/
public boolean isTopActivityPillarboxed() {
return topActivityLetterboxWidth < topActivityLetterboxHeight;
}
/**
- * @return {@code true} if the app compat parameters that are important for task organizers
+ * @return {@code true} if the app compat parameters that are important for task organizers
* are equal.
*/
public boolean equalsForTaskOrganizer(@Nullable AppCompatTaskInfo that) {
@@ -163,6 +176,8 @@
&& topActivityLetterboxVerticalPosition == that.topActivityLetterboxVerticalPosition
&& topActivityLetterboxWidth == that.topActivityLetterboxWidth
&& topActivityLetterboxHeight == that.topActivityLetterboxHeight
+ && topActivityLetterboxAppWidth == that.topActivityLetterboxAppWidth
+ && topActivityLetterboxAppHeight == that.topActivityLetterboxAppHeight
&& topActivityLetterboxHorizontalPosition
== that.topActivityLetterboxHorizontalPosition
&& isUserFullscreenOverrideEnabled == that.isUserFullscreenOverrideEnabled
@@ -189,6 +204,8 @@
== that.topActivityLetterboxHorizontalPosition
&& topActivityLetterboxWidth == that.topActivityLetterboxWidth
&& topActivityLetterboxHeight == that.topActivityLetterboxHeight
+ && topActivityLetterboxAppWidth == that.topActivityLetterboxAppWidth
+ && topActivityLetterboxAppHeight == that.topActivityLetterboxAppHeight
&& isUserFullscreenOverrideEnabled == that.isUserFullscreenOverrideEnabled
&& isSystemFullscreenOverrideEnabled == that.isSystemFullscreenOverrideEnabled
&& cameraCompatTaskInfo.equalsForCompatUi(that.cameraCompatTaskInfo);
@@ -209,6 +226,8 @@
topActivityLetterboxHorizontalPosition = source.readInt();
topActivityLetterboxWidth = source.readInt();
topActivityLetterboxHeight = source.readInt();
+ topActivityLetterboxAppWidth = source.readInt();
+ topActivityLetterboxAppHeight = source.readInt();
isUserFullscreenOverrideEnabled = source.readBoolean();
isSystemFullscreenOverrideEnabled = source.readBoolean();
cameraCompatTaskInfo = source.readTypedObject(CameraCompatTaskInfo.CREATOR);
@@ -230,6 +249,8 @@
dest.writeInt(topActivityLetterboxHorizontalPosition);
dest.writeInt(topActivityLetterboxWidth);
dest.writeInt(topActivityLetterboxHeight);
+ dest.writeInt(topActivityLetterboxAppWidth);
+ dest.writeInt(topActivityLetterboxAppHeight);
dest.writeBoolean(isUserFullscreenOverrideEnabled);
dest.writeBoolean(isSystemFullscreenOverrideEnabled);
dest.writeTypedObject(cameraCompatTaskInfo, flags);
@@ -251,6 +272,8 @@
+ topActivityLetterboxHorizontalPosition
+ " topActivityLetterboxWidth=" + topActivityLetterboxWidth
+ " topActivityLetterboxHeight=" + topActivityLetterboxHeight
+ + " topActivityLetterboxAppWidth=" + topActivityLetterboxAppWidth
+ + " topActivityLetterboxAppHeight=" + topActivityLetterboxAppHeight
+ " isUserFullscreenOverrideEnabled=" + isUserFullscreenOverrideEnabled
+ " isSystemFullscreenOverrideEnabled=" + isSystemFullscreenOverrideEnabled
+ " cameraCompatTaskInfo=" + cameraCompatTaskInfo.toString()
diff --git a/core/java/android/app/CameraCompatTaskInfo.java b/core/java/android/app/CameraCompatTaskInfo.java
index 1e116b7..53eddbe 100644
--- a/core/java/android/app/CameraCompatTaskInfo.java
+++ b/core/java/android/app/CameraCompatTaskInfo.java
@@ -31,45 +31,6 @@
*/
public class CameraCompatTaskInfo implements Parcelable {
/**
- * Camera compat control isn't shown because it's not requested by heuristics.
- */
- public static final int CAMERA_COMPAT_CONTROL_HIDDEN = 0;
-
- /**
- * Camera compat control is shown with the treatment suggested.
- */
- public static final int CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED = 1;
-
- /**
- * Camera compat control is shown to allow reverting the applied treatment.
- */
- public static final int CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED = 2;
-
- /**
- * Camera compat control is dismissed by user.
- */
- public static final int CAMERA_COMPAT_CONTROL_DISMISSED = 3;
-
- /**
- * Enum for the Camera app compat control states.
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = { "CAMERA_COMPAT_CONTROL_" }, value = {
- CAMERA_COMPAT_CONTROL_HIDDEN,
- CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED,
- CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED,
- CAMERA_COMPAT_CONTROL_DISMISSED,
- })
- public @interface CameraCompatControlState {}
-
- /**
- * State of the Camera app compat control which is used to correct stretched viewfinder
- * in apps that don't handle all possible configurations and changes between them correctly.
- */
- @CameraCompatControlState
- public int cameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN;
-
- /**
* The value to use when no camera compat treatment should be applied to a windowed task.
*/
public static final int CAMERA_COMPAT_FREEFORM_NONE = 0;
@@ -137,7 +98,6 @@
* Reads the CameraCompatTaskInfo from a parcel.
*/
void readFromParcel(Parcel source) {
- cameraCompatControlState = source.readInt();
freeformCameraCompatMode = source.readInt();
}
@@ -146,26 +106,10 @@
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(cameraCompatControlState);
dest.writeInt(freeformCameraCompatMode);
}
/**
- * @return {@value true} if the task has camera compat controls.
- */
- public boolean hasCameraCompatControl() {
- return cameraCompatControlState != CAMERA_COMPAT_CONTROL_HIDDEN
- && cameraCompatControlState != CAMERA_COMPAT_CONTROL_DISMISSED;
- }
-
- /**
- * @return {@value true} if the task has some compat ui.
- */
- public boolean hasCameraCompatUI() {
- return hasCameraCompatControl();
- }
-
- /**
* @return {@code true} if the camera compat parameters that are important for task organizers
* are equal.
*/
@@ -183,33 +127,16 @@
if (that == null) {
return false;
}
- return cameraCompatControlState == that.cameraCompatControlState
- && freeformCameraCompatMode == that.freeformCameraCompatMode;
+ return freeformCameraCompatMode == that.freeformCameraCompatMode;
}
@Override
public String toString() {
- return "CameraCompatTaskInfo { cameraCompatControlState="
- + cameraCompatControlStateToString(cameraCompatControlState)
- + " freeformCameraCompatMode="
+ return "CameraCompatTaskInfo { freeformCameraCompatMode="
+ freeformCameraCompatModeToString(freeformCameraCompatMode)
+ "}";
}
- /** Human readable version of the camera control state. */
- @NonNull
- public static String cameraCompatControlStateToString(
- @CameraCompatControlState int cameraCompatControlState) {
- return switch (cameraCompatControlState) {
- case CAMERA_COMPAT_CONTROL_HIDDEN -> "hidden";
- case CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED -> "treatment-suggested";
- case CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED -> "treatment-applied";
- case CAMERA_COMPAT_CONTROL_DISMISSED -> "dismissed";
- default -> throw new AssertionError(
- "Unexpected camera compat control state: " + cameraCompatControlState);
- };
- }
-
/** Human readable version of the freeform camera compat mode. */
@NonNull
public static String freeformCameraCompatModeToString(
diff --git a/core/java/android/app/IActivityClientController.aidl b/core/java/android/app/IActivityClientController.aidl
index 9c8fea1..9615015 100644
--- a/core/java/android/app/IActivityClientController.aidl
+++ b/core/java/android/app/IActivityClientController.aidl
@@ -17,7 +17,6 @@
package android.app;
import android.app.ActivityManager;
-import android.app.ICompatCameraControlCallback;
import android.app.IRequestFinishCallback;
import android.app.PictureInPictureParams;
import android.content.ComponentName;
@@ -172,17 +171,6 @@
oneway void splashScreenAttached(in IBinder token);
/**
- * Shows or hides a Camera app compat toggle for stretched issues with the requested state.
- *
- * @param token The token for the window that needs a control.
- * @param showControl Whether the control should be shown or hidden.
- * @param transformationApplied Whether the treatment is already applied.
- * @param callback The callback executed when the user clicks on a control.
- */
- oneway void requestCompatCameraControl(in IBinder token, boolean showControl,
- boolean transformationApplied, in ICompatCameraControlCallback callback);
-
- /**
* If set, any activity launch in the same task will be overridden to the locale of activity
* that started the task.
*/
diff --git a/core/java/android/app/ICompatCameraControlCallback.aidl b/core/java/android/app/ICompatCameraControlCallback.aidl
deleted file mode 100644
index 1a7f210..0000000
--- a/core/java/android/app/ICompatCameraControlCallback.aidl
+++ /dev/null
@@ -1,30 +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 android.app;
-
-/**
- * This callback allows ActivityRecord to ask the calling View to apply the treatment for stretched
- * issues affecting camera viewfinders when the user clicks on the camera compat control.
- *
- * {@hide}
- */
-oneway interface ICompatCameraControlCallback {
-
- void applyCameraCompatTreatment();
-
- void revertCameraCompatTreatment();
-}
diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS
index 1200b4b..adeb045 100644
--- a/core/java/android/app/OWNERS
+++ b/core/java/android/app/OWNERS
@@ -94,6 +94,9 @@
per-file IInstantAppResolver.aidl = file:/services/core/java/com/android/server/pm/OWNERS
per-file InstantAppResolveInfo.aidl = file:/services/core/java/com/android/server/pm/OWNERS
+# Performance
+per-file PropertyInvalidatedCache.java = file:/PERFORMANCE_OWNERS
+
# Pinner
per-file pinner-client.aconfig = file:/core/java/android/app/pinner/OWNERS
diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java
index 27f9f54..0c786cb 100644
--- a/core/java/android/app/PropertyInvalidatedCache.java
+++ b/core/java/android/app/PropertyInvalidatedCache.java
@@ -29,6 +29,7 @@
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.BackgroundThread;
import com.android.internal.util.FastPrintWriter;
import java.lang.annotation.Retention;
@@ -1260,7 +1261,7 @@
}
public void autoCork() {
- if (Looper.getMainLooper() == null) {
+ if (getLooper() == null) {
// We're not ready to auto-cork yet, so just invalidate the cache immediately.
if (DEBUG) {
Log.w(TAG, "invalidating instead of autocorking early in init: "
@@ -1322,7 +1323,7 @@
@GuardedBy("mLock")
private Handler getHandlerLocked() {
if (mHandler == null) {
- mHandler = new Handler(Looper.getMainLooper()) {
+ mHandler = new Handler(getLooper()) {
@Override
public void handleMessage(Message msg) {
AutoCorker.this.handleMessage(msg);
@@ -1331,6 +1332,14 @@
}
return mHandler;
}
+
+ /**
+ * Return a looper for auto-uncork messages. Messages should be processed on the
+ * background thread, not on the main thread.
+ */
+ private static Looper getLooper() {
+ return BackgroundThread.getHandler().getLooper();
+ }
}
/**
@@ -1617,18 +1626,4 @@
Log.e(TAG, "Failed to dump PropertyInvalidatedCache instances");
}
}
-
- /**
- * Trim memory by clearing all the caches.
- * @hide
- */
- public static void onTrimMemory() {
- ArrayList<PropertyInvalidatedCache> activeCaches;
- synchronized (sGlobalLock) {
- activeCaches = getActiveCaches();
- }
- for (int i = 0; i < activeCaches.size(); i++) {
- activeCaches.get(i).clear();
- }
- }
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index a7070b9..965e3c4 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -11964,6 +11964,34 @@
}
/**
+ * Adds a user restriction on {@code targetUser}, specified by the {@code key}.
+ *
+ * <p>Called by a system service only, meaning that the caller's UID must be equal to
+ * {@link Process#SYSTEM_UID}.
+ *
+ * @param systemEntity The service entity that adds the restriction. A user restriction set by
+ * a service entity can only be cleared by the same entity. This can be
+ * just the calling package name, or any string of the caller's choice
+ * can be used.
+ * @param key The key of the restriction.
+ * @param targetUser The user to add the restriction on.
+ * @throws SecurityException if the caller is not a system service
+ *
+ * @hide
+ */
+ public void addUserRestriction(@NonNull String systemEntity,
+ @NonNull @UserManager.UserRestrictionKey String key, @UserIdInt int targetUser) {
+ if (mService != null) {
+ try {
+ mService.setUserRestrictionForUser(
+ systemEntity, key, /* enable= */ true, targetUser);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
* Called by a profile owner, device owner or a holder of any permission that is associated with
* a user restriction to set a user restriction specified by the provided {@code key} globally
* on all users. To clear the restriction use {@link #clearUserRestriction}.
@@ -11971,7 +11999,7 @@
* <p>For a given user, a restriction will be set if it was applied globally or locally by any
* admin.
*
- * <p> The calling device admin must be a profile owner, device owner or or a holder of any
+ * <p> The calling device admin must be a profile owner, device owner or a holder of any
* permission that is associated with a user restriction; if it is not, a security
* exception will be thrown.
*
@@ -12072,6 +12100,34 @@
}
/**
+ * Clears a user restriction from {@code targetUser}, specified by the {@code key}.
+ *
+ * <p>Called by a system service only, meaning that the caller's UID must be equal to
+ * {@link Process#SYSTEM_UID}.
+ *
+ * @param systemEntity The system entity that clears the restriction. A user restriction
+ * set by a system entity can only be cleared by the same entity. This
+ * can be just the calling package name, or any string of the caller's
+ * choice can be used.
+ * @param key The key of the restriction.
+ * @param targetUser The user to clear the restriction from.
+ * @throws SecurityException if the caller is not a system service
+ *
+ * @hide
+ */
+ public void clearUserRestriction(@NonNull String systemEntity,
+ @NonNull @UserManager.UserRestrictionKey String key, @UserIdInt int targetUser) {
+ if (mService != null) {
+ try {
+ mService.setUserRestrictionForUser(
+ systemEntity, key, /* enable= */ false, targetUser);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
* Called by an admin to get user restrictions set by themselves with
* {@link #addUserRestriction(ComponentName, String)}.
* <p>
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 381f996..c393a9e 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -255,6 +255,7 @@
ComponentName getRestrictionsProvider(int userHandle);
void setUserRestriction(in ComponentName who, in String callerPackage, in String key, boolean enable, boolean parent);
+ void setUserRestrictionForUser(in String systemEntity, in String key, boolean enable, int targetUser);
void setUserRestrictionGlobally(in String callerPackage, in String key);
Bundle getUserRestrictions(in ComponentName who, in String callerPackage, boolean parent);
Bundle getUserRestrictionsGlobally(in String callerPackage);
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 1f19f81..933c336 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -132,7 +132,7 @@
* Create a host view. Uses specified animations when pushing
* {@link #updateAppWidget(RemoteViews)}.
*
- * @param animationIn Resource ID of in animation to use
+ * @param animationIn Resource ID of in animation to use
* @param animationOut Resource ID of out animation to use
*/
@SuppressWarnings({"UnusedDeclaration"})
@@ -148,7 +148,7 @@
* Pass the given handler to RemoteViews when updating this widget. Unless this
* is done immediatly after construction, a call to {@link #updateAppWidget(RemoteViews)}
* should be made.
- * @param handler
+ *
* @hide
*/
public void setInteractionHandler(InteractionHandler handler) {
@@ -206,10 +206,10 @@
* order for the AppWidgetHost to account for the automatic padding when computing the number
* of cells to allocate to a particular widget.
*
- * @param context the current context
+ * @param context the current context
* @param component the component name of the widget
- * @param padding Rect in which to place the output, if null, a new Rect will be allocated and
- * returned
+ * @param padding Rect in which to place the output, if null, a new Rect will be allocated and
+ * returned
* @return default padding for this widget, in pixels
*/
public static Rect getDefaultPaddingForWidget(Context context, ComponentName component,
@@ -291,7 +291,7 @@
}
mDelayedRestoredInflationId = -1;
mDelayedRestoredState = null;
- try {
+ try {
super.dispatchRestoreInstanceState(state);
} catch (Exception e) {
Log.e(TAG, "failed to restoreInstanceState for widget id: " + mAppWidgetId + ", "
@@ -354,14 +354,14 @@
* the framework will be accounted for automatically. This information gets embedded into the
* AppWidget options and causes a callback to the AppWidgetProvider. In addition, the list of
* sizes is explicitly set to an empty list.
- * @see AppWidgetProvider#onAppWidgetOptionsChanged(Context, AppWidgetManager, int, Bundle)
*
* @param newOptions The bundle of options, in addition to the size information,
- * can be null.
- * @param minWidth The minimum width in dips that the widget will be displayed at.
- * @param minHeight The maximum height in dips that the widget will be displayed at.
- * @param maxWidth The maximum width in dips that the widget will be displayed at.
- * @param maxHeight The maximum height in dips that the widget will be displayed at.
+ * can be null.
+ * @param minWidth The minimum width in dips that the widget will be displayed at.
+ * @param minHeight The maximum height in dips that the widget will be displayed at.
+ * @param maxWidth The maximum width in dips that the widget will be displayed at.
+ * @param maxHeight The maximum height in dips that the widget will be displayed at.
+ * @see AppWidgetProvider#onAppWidgetOptionsChanged(Context, AppWidgetManager, int, Bundle)
* @deprecated use {@link AppWidgetHostView#updateAppWidgetSize(Bundle, List)} instead.
*/
@Deprecated
@@ -378,12 +378,14 @@
* This method will update the option bundle with the list of sizes and the min/max bounds for
* width and height.
*
- * @see AppWidgetProvider#onAppWidgetOptionsChanged(Context, AppWidgetManager, int, Bundle)
- *
* @param newOptions The bundle of options, in addition to the size information.
- * @param sizes Sizes, in dips, the widget may be displayed at without calling the provider
- * again. Typically, this will be size of the widget in landscape and portrait.
- * On some foldables, this might include the size on the outer and inner screens.
+ * @param sizes Sizes, in dips, the widget may be displayed at without calling the
+ * provider
+ * again. Typically, this will be size of the widget in landscape and
+ * portrait.
+ * On some foldables, this might include the size on the outer and inner
+ * screens.
+ * @see AppWidgetProvider#onAppWidgetOptionsChanged(Context, AppWidgetManager, int, Bundle)
*/
public void updateAppWidgetSize(@NonNull Bundle newOptions, @NonNull List<SizeF> sizes) {
AppWidgetManager widgetManager = AppWidgetManager.getInstance(mContext);
@@ -470,9 +472,9 @@
/**
* Specify some extra information for the widget provider. Causes a callback to the
* AppWidgetProvider.
- * @see AppWidgetProvider#onAppWidgetOptionsChanged(Context, AppWidgetManager, int, Bundle)
*
* @param options The bundle of options information.
+ * @see AppWidgetProvider#onAppWidgetOptionsChanged(Context, AppWidgetManager, int, Bundle)
*/
public void updateAppWidgetOptions(Bundle options) {
AppWidgetManager.getInstance(mContext).updateAppWidgetOptions(mAppWidgetId, options);
@@ -507,6 +509,7 @@
/**
* Sets whether the widget is being displayed on a light/white background and use an
* alternate UI if available.
+ *
* @see RemoteViews#setLightBackgroundLayoutId(int)
*/
public void setOnLightBackground(boolean onLightBackground) {
@@ -620,7 +623,7 @@
if (content == null) {
if (mViewMode == VIEW_MODE_ERROR) {
// We've already done this -- nothing to do.
- return ;
+ return;
}
if (exception != null) {
Log.w(TAG, "Error inflating RemoteViews", exception);
@@ -733,7 +736,7 @@
if (adapter instanceof BaseAdapter) {
BaseAdapter baseAdapter = (BaseAdapter) adapter;
baseAdapter.notifyDataSetChanged();
- } else if (adapter == null && adapterView instanceof RemoteAdapterConnectionCallback) {
+ } else if (adapter == null && adapterView instanceof RemoteAdapterConnectionCallback) {
// If the adapter is null, it may mean that the RemoteViewsAapter has not yet
// connected to its associated service, and hence the adapter hasn't been set.
// In this case, we need to defer the notify call until it has been set.
@@ -745,6 +748,7 @@
/**
* Build a {@link Context} cloned into another package name, usually for the
* purposes of reading remote resources.
+ *
* @hide
*/
protected Context getRemoteContextEnsuringCorrectCachedApkPath() {
@@ -760,7 +764,7 @@
}
return newContext;
} catch (NameNotFoundException e) {
- Log.e(TAG, "Package name " + mInfo.providerInfo.packageName + " not found");
+ Log.e(TAG, "Package name " + mInfo.providerInfo.packageName + " not found");
return mContext;
} catch (NullPointerException e) {
Log.e(TAG, "Error trying to create the remote context.", e);
@@ -774,7 +778,7 @@
*/
protected void prepareView(View view) {
// Take requested dimensions from child, but apply default gravity.
- FrameLayout.LayoutParams requested = (FrameLayout.LayoutParams)view.getLayoutParams();
+ FrameLayout.LayoutParams requested = (FrameLayout.LayoutParams) view.getLayoutParams();
if (requested == null) {
requested = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
@@ -839,7 +843,18 @@
return defaultView;
}
- private void onDefaultViewClicked(View view) {
+ /**
+ * Handles interactions on the default view of the widget. By default does not use the
+ * {@link InteractionHandler} used by other interactions. However, this can be overridden
+ * in order to customize the click behavior.
+ *
+ * @hide
+ */
+ protected void onDefaultViewClicked(@NonNull View view) {
+ final AppWidgetManager manager = AppWidgetManager.getInstance(mContext);
+ if (manager != null) {
+ manager.noteAppWidgetTapped(mAppWidgetId);
+ }
if (mInfo != null) {
LauncherApps launcherApps = getContext().getSystemService(LauncherApps.class);
List<LauncherActivityInfo> activities = launcherApps.getActivityList(
diff --git a/core/java/android/companion/virtual/IVirtualDevice.aidl b/core/java/android/companion/virtual/IVirtualDevice.aidl
index 0653839..a56bc02 100644
--- a/core/java/android/companion/virtual/IVirtualDevice.aidl
+++ b/core/java/android/companion/virtual/IVirtualDevice.aidl
@@ -112,6 +112,24 @@
void removeActivityPolicyExemption(in ComponentName exemption);
/**
+ * Specifies a policy for this virtual device on the given display.
+ */
+ @EnforcePermission("CREATE_VIRTUAL_DEVICE")
+ void setDevicePolicyForDisplay(int displayId, int policyType, int devicePolicy);
+
+ /**
+ * Adds an exemption to the default activity launch policy on the given display.
+ */
+ @EnforcePermission("CREATE_VIRTUAL_DEVICE")
+ void addActivityPolicyExemptionForDisplay(int displayId, in ComponentName exemption);
+
+ /**
+ * Removes an exemption to the default activity launch policy on the given display.
+ */
+ @EnforcePermission("CREATE_VIRTUAL_DEVICE")
+ void removeActivityPolicyExemptionForDisplay(int displayId, in ComponentName exemption);
+
+ /**
* Notifies that an audio session being started.
*/
@EnforcePermission("CREATE_VIRTUAL_DEVICE")
diff --git a/core/java/android/companion/virtual/IVirtualDeviceActivityListener.aidl b/core/java/android/companion/virtual/IVirtualDeviceActivityListener.aidl
index 39371a3..564fb02 100644
--- a/core/java/android/companion/virtual/IVirtualDeviceActivityListener.aidl
+++ b/core/java/android/companion/virtual/IVirtualDeviceActivityListener.aidl
@@ -17,6 +17,7 @@
package android.companion.virtual;
import android.content.ComponentName;
+import android.content.IntentSender;
/**
* Interface to listen for activity changes in a virtual device.
@@ -48,6 +49,8 @@
* @param displayId The display ID on which the activity tried to launch.
* @param componentName The component name of the blocked activity.
* @param userId The user ID associated with the blocked activity.
+ * @param intentSender The original sender of the intent.
*/
- void onActivityLaunchBlocked(int displayId, in ComponentName componentName, int userId);
+ void onActivityLaunchBlocked(int displayId, in ComponentName componentName, int userId,
+ in IntentSender intentSender);
}
diff --git a/core/java/android/companion/virtual/VirtualDeviceInternal.java b/core/java/android/companion/virtual/VirtualDeviceInternal.java
index d3fcfc6..19eb497 100644
--- a/core/java/android/companion/virtual/VirtualDeviceInternal.java
+++ b/core/java/android/companion/virtual/VirtualDeviceInternal.java
@@ -17,7 +17,11 @@
package android.companion.virtual;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
+import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_ACTIVITY;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO;
+import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_BLOCKED_ACTIVITY_BEHAVIOR;
+import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_CLIPBOARD;
+import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_RECENTS;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
@@ -34,6 +38,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.IntentSender;
import android.hardware.display.DisplayManagerGlobal;
import android.hardware.display.IVirtualDisplayCallback;
import android.hardware.display.VirtualDisplay;
@@ -131,13 +136,14 @@
@Override
public void onActivityLaunchBlocked(int displayId, ComponentName componentName,
- @UserIdInt int userId) {
+ @UserIdInt int userId, IntentSender intentSender) {
final long token = Binder.clearCallingIdentity();
try {
synchronized (mActivityListenersLock) {
for (int i = 0; i < mActivityListeners.size(); i++) {
mActivityListeners.valueAt(i)
- .onActivityLaunchBlocked(displayId, componentName, userId);
+ .onActivityLaunchBlocked(
+ displayId, componentName, userId, intentSender);
}
}
} finally {
@@ -282,6 +288,16 @@
void setDevicePolicy(@VirtualDeviceParams.DynamicPolicyType int policyType,
@VirtualDeviceParams.DevicePolicy int devicePolicy) {
+ switch (policyType) {
+ case POLICY_TYPE_RECENTS:
+ case POLICY_TYPE_CLIPBOARD:
+ case POLICY_TYPE_ACTIVITY:
+ case POLICY_TYPE_BLOCKED_ACTIVITY_BEHAVIOR:
+ break;
+ default:
+ throw new IllegalArgumentException("Device policy " + policyType
+ + " cannot be changed at runtime. ");
+ }
try {
mVirtualDevice.setDevicePolicy(policyType, devicePolicy);
} catch (RemoteException e) {
@@ -305,6 +321,42 @@
}
}
+ void setDevicePolicyForDisplay(int displayId,
+ @VirtualDeviceParams.DynamicDisplayPolicyType int policyType,
+ @VirtualDeviceParams.DevicePolicy int devicePolicy) {
+ switch (policyType) {
+ case POLICY_TYPE_RECENTS:
+ case POLICY_TYPE_ACTIVITY:
+ break;
+ default:
+ throw new IllegalArgumentException("Device policy " + policyType
+ + " cannot be changed for a specific display. ");
+ }
+
+ try {
+ mVirtualDevice.setDevicePolicyForDisplay(displayId, policyType, devicePolicy);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ void addActivityPolicyExemptionForDisplay(int displayId, @NonNull ComponentName componentName) {
+ try {
+ mVirtualDevice.addActivityPolicyExemptionForDisplay(displayId, componentName);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ void removeActivityPolicyExemptionForDisplay(int displayId,
+ @NonNull ComponentName componentName) {
+ try {
+ mVirtualDevice.removeActivityPolicyExemptionForDisplay(displayId, componentName);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
@NonNull
VirtualDpad createVirtualDpad(@NonNull VirtualDpadConfig config) {
try {
@@ -543,9 +595,10 @@
}
public void onActivityLaunchBlocked(int displayId, ComponentName componentName,
- @UserIdInt int userId) {
+ @UserIdInt int userId, IntentSender intentSender) {
mExecutor.execute(() ->
- mActivityListener.onActivityLaunchBlocked(displayId, componentName, userId));
+ mActivityListener.onActivityLaunchBlocked(
+ displayId, componentName, userId, intentSender));
}
}
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
index 296ca33..8b60580 100644
--- a/core/java/android/companion/virtual/VirtualDeviceManager.java
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -43,6 +43,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.IntentSender;
import android.graphics.Point;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.VirtualDisplayFlag;
@@ -739,6 +740,7 @@
*
* @param policyType the type of policy, i.e. which behavior to specify a policy for.
* @param devicePolicy the value of the policy, i.e. how to interpret the device behavior.
+ * @throws IllegalArgumentException if the policy cannot be changed at runtime.
*
* @see VirtualDeviceParams#POLICY_TYPE_RECENTS
* @see VirtualDeviceParams#POLICY_TYPE_ACTIVITY
@@ -797,6 +799,95 @@
}
/**
+ * Specifies a policy for this virtual device to be applied on the given virtual display.
+ * <p>
+ * Any policy specified for a particular display takes precedence over the policy specified
+ * for the device itself.
+ * </p>
+ *
+ * @param policyType the type of policy, i.e. which behavior to specify a policy for.
+ * @param devicePolicy the value of the policy, i.e. how to interpret the device behavior.
+ * @param displayId the ID of the display, for which to apply the policy.
+ * @throws IllegalArgumentException if the specified policy cannot be changed per
+ * display or if the specified display does not belong to the virtual device.
+ *
+ * @see #setDevicePolicy(int, int)
+ * @see VirtualDeviceParams#POLICY_TYPE_RECENTS
+ * @see VirtualDeviceParams#POLICY_TYPE_ACTIVITY
+ */
+ @FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_ACTIVITY_CONTROL_API)
+ @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
+ public void setDevicePolicy(
+ @VirtualDeviceParams.DynamicDisplayPolicyType int policyType,
+ @VirtualDeviceParams.DevicePolicy int devicePolicy,
+ int displayId) {
+ mVirtualDeviceInternal.setDevicePolicyForDisplay(displayId, policyType, devicePolicy);
+ }
+
+ /**
+ * Specifies a component name to be exempt from the given display's activity launch policy.
+ *
+ * <p>If the current {@link VirtualDeviceParams#POLICY_TYPE_ACTIVITY} allows activity
+ * launches by default, (i.e. it is {@link VirtualDeviceParams#DEVICE_POLICY_DEFAULT}),
+ * then the specified component will be blocked from launching.
+ * If the current {@link VirtualDeviceParams#POLICY_TYPE_ACTIVITY} blocks activity launches
+ * by default, (i.e. it is {@link VirtualDeviceParams#DEVICE_POLICY_CUSTOM}), then the
+ * specified component will be allowed to launch.</p>
+ *
+ * <p>Note that changing the activity launch policy will clear current set of exempt
+ * components.</p>
+ * <p>Any change to the exemptions will only be applied for new activity launches.</p>
+ *
+ * @param componentName the component name to be exempt from the activity launch policy.
+ * @param displayId the ID of the display, for which to apply the exemption. The display
+ * must belong to the virtual device.
+ * @throws IllegalArgumentException if the specified display does not belong to the virtual
+ * device.
+ *
+ * @see #removeActivityPolicyExemption
+ * @see #setDevicePolicy
+ * @see Display#getDisplayId
+ */
+ @FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_ACTIVITY_CONTROL_API)
+ @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
+ public void addActivityPolicyExemption(
+ @NonNull ComponentName componentName, int displayId) {
+ mVirtualDeviceInternal.addActivityPolicyExemptionForDisplay(
+ displayId, Objects.requireNonNull(componentName));
+ }
+
+ /**
+ * Makes the specified component name adhere to the given display's activity launch policy.
+ *
+ * <p>If the current {@link VirtualDeviceParams#POLICY_TYPE_ACTIVITY} allows activity
+ * launches by default, (i.e. it is {@link VirtualDeviceParams#DEVICE_POLICY_DEFAULT}),
+ * then the specified component will be allowed to launch.
+ * If the current {@link VirtualDeviceParams#POLICY_TYPE_ACTIVITY} blocks activity launches
+ * by default, (i.e. it is {@link VirtualDeviceParams#DEVICE_POLICY_CUSTOM}), then the
+ * specified component will be blocked from launching.</p>
+ *
+ * <p>Note that changing the activity launch policy will clear current set of exempt
+ * components.</p>
+ *
+ * @param componentName the component name to be removed from the exemption list.
+ * @param displayId the ID of the display, for which to apply the exemption. The display
+ * must belong to the virtual device.
+ * @throws IllegalArgumentException if the specified display does not belong to the virtual
+ * device.
+ *
+ * @see #addActivityPolicyExemption
+ * @see #setDevicePolicy
+ * @see Display#getDisplayId
+ */
+ @FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_ACTIVITY_CONTROL_API)
+ @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
+ public void removeActivityPolicyExemption(
+ @NonNull ComponentName componentName, int displayId) {
+ mVirtualDeviceInternal.removeActivityPolicyExemptionForDisplay(
+ displayId, Objects.requireNonNull(componentName));
+ }
+
+ /**
* Creates a virtual dpad.
*
* @param config the configurations of the virtual dpad.
@@ -1174,13 +1265,18 @@
* @param displayId The display ID on which the activity tried to launch.
* @param componentName The component name of the blocked activity.
* @param userId The user ID associated with the blocked activity.
+ * @param intentSender The original sender of the intent. May be {@code null} if the sender
+ * expects an activity result to be reported. In that case
+ * {@link android.app.Activity#RESULT_CANCELED} was already reported back because the
+ * launch was blocked. This {@link IntentSender} can be used to relaunch the blocked
+ * activity to a different display.
*
* @see VirtualDeviceParams#POLICY_TYPE_ACTIVITY
* @see VirtualDevice#addActivityPolicyExemption(ComponentName)
*/
@FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_ACTIVITY_CONTROL_API)
default void onActivityLaunchBlocked(int displayId, @NonNull ComponentName componentName,
- @UserIdInt int userId) {}
+ @UserIdInt int userId, @Nullable IntentSender intentSender) {}
}
/**
diff --git a/core/java/android/companion/virtual/VirtualDeviceParams.java b/core/java/android/companion/virtual/VirtualDeviceParams.java
index f7f842f..c1fc51d 100644
--- a/core/java/android/companion/virtual/VirtualDeviceParams.java
+++ b/core/java/android/companion/virtual/VirtualDeviceParams.java
@@ -159,7 +159,8 @@
* @hide
*/
@IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_SENSORS, POLICY_TYPE_AUDIO,
- POLICY_TYPE_RECENTS, POLICY_TYPE_ACTIVITY, POLICY_TYPE_CAMERA})
+ POLICY_TYPE_RECENTS, POLICY_TYPE_ACTIVITY, POLICY_TYPE_CAMERA,
+ POLICY_TYPE_BLOCKED_ACTIVITY_BEHAVIOR})
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
public @interface PolicyType {}
@@ -177,6 +178,17 @@
public @interface DynamicPolicyType {}
/**
+ * Policy types that can be dynamically changed for a specific display.
+ *
+ * @see VirtualDeviceManager.VirtualDevice#setDevicePolicyForDisplay
+ * @hide
+ */
+ @IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_RECENTS, POLICY_TYPE_ACTIVITY})
+ @Retention(RetentionPolicy.SOURCE)
+ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
+ public @interface DynamicDisplayPolicyType {}
+
+ /**
* Tells the sensor framework how to handle sensor requests from contexts associated with this
* virtual device, namely the sensors returned by
* {@link android.hardware.SensorManager#getSensorList}:
@@ -229,6 +241,8 @@
* @see VirtualDeviceManager.VirtualDevice#addActivityPolicyExemption
* @see VirtualDeviceManager.VirtualDevice#removeActivityPolicyExemption
*/
+ // TODO(b/333443509): Update the documentation of custom policy and link to the new policy
+ // POLICY_TYPE_BLOCKED_ACTIVITY_BEHAVIOR
@FlaggedApi(Flags.FLAG_DYNAMIC_POLICY)
public static final int POLICY_TYPE_ACTIVITY = 3;
@@ -276,6 +290,7 @@
* experience on the virtual device.
* </ul>
*/
+ // TODO(b/333443509): Link to POLICY_TYPE_ACTIVITY
@FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_ACTIVITY_CONTROL_API)
public static final int POLICY_TYPE_BLOCKED_ACTIVITY_BEHAVIOR = 6;
diff --git a/core/java/android/companion/virtual/flags.aconfig b/core/java/android/companion/virtual/flags.aconfig
index b29b52d..91586b6 100644
--- a/core/java/android/companion/virtual/flags.aconfig
+++ b/core/java/android/companion/virtual/flags.aconfig
@@ -81,13 +81,6 @@
}
flag {
- name: "stream_permissions"
- namespace: "virtual_devices"
- description: "Enable streaming permission dialogs to Virtual Devices"
- bug: "291737919"
-}
-
-flag {
name: "persistent_device_id_api"
is_exported: true
namespace: "virtual_devices"
@@ -96,13 +89,6 @@
}
flag {
- name: "express_metrics"
- namespace: "virtual_devices"
- description: "Enable express metrics in VDM"
- bug: "307297730"
-}
-
-flag {
name: "interactive_screen_mirror"
is_exported: true
namespace: "virtual_devices"
@@ -119,17 +105,6 @@
}
flag {
- name: "intercept_intents_before_applying_policy"
- is_exported: true
- namespace: "virtual_devices"
- description: "Apply intent interception before applying activity policy"
- bug: "333444131"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "impulse_velocity_strategy_for_touch_navigation"
is_exported: true
namespace: "virtual_devices"
diff --git a/core/java/android/companion/virtual/flags/flags.aconfig b/core/java/android/companion/virtual/flags/flags.aconfig
index a1ae9da..c3c3f0e 100644
--- a/core/java/android/companion/virtual/flags/flags.aconfig
+++ b/core/java/android/companion/virtual/flags/flags.aconfig
@@ -47,14 +47,6 @@
flag {
namespace: "virtual_devices"
- name: "metrics_collection"
- description: "Enable collection of VDM-related metrics"
- bug: "324842215"
- is_fixed_read_only: true
-}
-
-flag {
- namespace: "virtual_devices"
name: "activity_control_api"
description: "Enable APIs for fine grained activity policy, fallback and callbacks"
bug: "333443509"
@@ -92,27 +84,6 @@
flag {
namespace: "virtual_devices"
- name: "virtual_display_multi_window_mode_support"
- description: "Add support for WINDOWING_MODE_MULTI_WINDOW to virtual displays by default"
- is_fixed_read_only: true
- bug: "341151395"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
- namespace: "virtual_devices"
- name: "intent_interception_action_matching_fix"
- description: "Do not match intents without actions if the filter has actions"
- bug: "343805037"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
- namespace: "virtual_devices"
name: "virtual_display_rotation_api"
description: "API for on-demand rotation of virtual displays"
bug: "291748430"
diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java
index d7195a7..964a8be 100644
--- a/core/java/android/content/BroadcastReceiver.java
+++ b/core/java/android/content/BroadcastReceiver.java
@@ -34,6 +34,8 @@
import android.util.Log;
import android.util.Slog;
+import com.android.internal.os.DebugStore;
+
/**
* Base class for code that receives and handles broadcast intents sent by
* {@link android.content.Context#sendBroadcast(Intent)}.
@@ -55,6 +57,9 @@
private PendingResult mPendingResult;
private boolean mDebugUnregister;
+ private static final boolean DEBUG_STORE_ENABLED =
+ com.android.internal.os.Flags.debugStoreEnabled();
+
/**
* State for a result that is pending for a broadcast receiver. Returned
* by {@link BroadcastReceiver#goAsync() goAsync()}
@@ -255,6 +260,9 @@
"PendingResult#finish#ClassName:" + mReceiverClassName,
1);
}
+ if (DEBUG_STORE_ENABLED) {
+ DebugStore.recordFinish(mReceiverClassName);
+ }
if (mType == TYPE_COMPONENT) {
final IActivityManager mgr = ActivityManager.getService();
@@ -433,7 +441,9 @@
public final PendingResult goAsync() {
PendingResult res = mPendingResult;
mPendingResult = null;
-
+ if (DEBUG_STORE_ENABLED) {
+ DebugStore.recordGoAsync(getClass().getName());
+ }
if (res != null && Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
res.mReceiverClassName = getClass().getName();
Trace.traceCounter(Trace.TRACE_TAG_ACTIVITY_MANAGER,
diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig
index d9b0e6d..7c2edd7 100644
--- a/core/java/android/content/pm/flags.aconfig
+++ b/core/java/android/content/pm/flags.aconfig
@@ -237,6 +237,8 @@
bug: "307327678"
}
+# This flag is enabled since V but not a MUST requirement in CDD yet, so it needs to stay around
+# for now and any code working with it should keep checking the flag.
flag {
name: "restrict_nonpreloads_system_shareduids"
namespace: "package_manager_service"
diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig
index 6882d5c..835459e 100644
--- a/core/java/android/content/pm/multiuser.aconfig
+++ b/core/java/android/content/pm/multiuser.aconfig
@@ -171,6 +171,16 @@
}
flag {
+ name: "fix_disabling_of_mu_toggle_when_restriction_applied"
+ namespace: "multiuser"
+ description: "When no_user_switch is set but no EnforcedAdmin is present, the toggle has to be disabled"
+ bug: "356387759"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "cache_quiet_mode_state"
namespace: "multiuser"
description: "Optimise quiet mode state retrieval"
@@ -369,3 +379,10 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "unicorn_mode_refactoring_for_hsum"
+ namespace: "multiuser"
+ description: "Refactorings related to unicorn mode to work on HSUM mode"
+ bug: "339201286"
+}
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index e0dc568..914aa51 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -34,17 +34,22 @@
import android.util.LruCache;
import android.util.Pair;
import android.util.Printer;
+import com.android.internal.util.RingBuffer;
import dalvik.system.BlockGuard;
import dalvik.system.CloseGuard;
+
import java.io.File;
import java.io.IOException;
import java.lang.ref.Reference;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
+import java.util.Locale;
import java.util.Map;
import java.util.function.BinaryOperator;
import java.util.function.UnaryOperator;
@@ -185,7 +190,7 @@
SQLiteDatabaseConfiguration configuration,
int connectionId, boolean primaryConnection) {
mPool = pool;
- mRecentOperations = new OperationLog(mPool);
+ mRecentOperations = new OperationLog();
mConfiguration = new SQLiteDatabaseConfiguration(configuration);
mConnectionId = connectionId;
mIsPrimaryConnection = primaryConnection;
@@ -305,6 +310,16 @@
}
}
+ /** Record the start of a transaction for logging and debugging. */
+ void recordBeginTransaction(String mode) {
+ mRecentOperations.beginTransaction(mode);
+ }
+
+ /** Record the end of a transaction for logging and debugging. */
+ void recordEndTransaction(boolean successful) {
+ mRecentOperations.endTransaction(successful);
+ }
+
private void setPageSize() {
if (!mConfiguration.isInMemoryDb() && !mIsReadOnlyConnection) {
final long newValue = SQLiteGlobal.getDefaultPageSize();
@@ -1335,6 +1350,7 @@
}
printer.println(" isPrimaryConnection: " + mIsPrimaryConnection);
printer.println(" onlyAllowReadOnlyOperations: " + mOnlyAllowReadOnlyOperations);
+ printer.println(" totalLongOperations: " + mRecentOperations.getTotalLongOperations());
mRecentOperations.dump(printer);
@@ -1593,51 +1609,84 @@
}
}
- private static final class OperationLog {
+ /**
+ * This class implements a leaky bucket strategy to rate-limit operations. A client
+ * accumulates one credit every <n> milliseconds; a credit allows the client execute an
+ * operation (which then deducts the credit). Credits accumulate up to a maximum amount after
+ * which they no longer accumulate. The strategy allows a client to execute an operation
+ * every <n> milliseconds, or to execute a burst, after a period of no operations.
+ */
+ private static class RateLimiter {
+ // When the bucket was created, in ms.
+ private final long mCreationUptimeMs;
+ // The time required to accumulate a single credit.
+ private final long mMsPerCredit;
+ // The maximum number of credits the process can accumulate.
+ private final int mMaxCredits;
+ // Total credits consumed so far.
+ private long mSpent = 0;
+
+ RateLimiter(long msPerCredit, int maxCredits) {
+ mMsPerCredit = msPerCredit;
+ mMaxCredits = maxCredits;
+ mCreationUptimeMs = SystemClock.uptimeMillis() - (mMsPerCredit * mMaxCredits);
+ }
+
+ /** Return true if there is a credit available (and consume that credit). */
+ boolean tryAcquire() {
+ final long now = SystemClock.uptimeMillis();
+ long credits = (now - mCreationUptimeMs) / mMsPerCredit;
+
+ long available = credits - mSpent;
+ if (available > mMaxCredits) {
+ mSpent += available - mMaxCredits;
+ available = credits - mSpent;
+ }
+ if (available > 0) {
+ mSpent++;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ private final class OperationLog {
private static final int MAX_RECENT_OPERATIONS = 20;
private static final int COOKIE_GENERATION_SHIFT = 8;
private static final int COOKIE_INDEX_MASK = 0xff;
+ // Operations over 2s are long. Save the last ten.
+ private static final long LONG_OPERATION_THRESHOLD_MS = 2_000;
+ private static final int MAX_LONG_OPERATIONS = 10;
+
private final Operation[] mOperations = new Operation[MAX_RECENT_OPERATIONS];
- private int mIndex;
- private int mGeneration;
- private final SQLiteConnectionPool mPool;
+ private int mIndex = -1;
+ private int mGeneration = 0;
+ private final Operation mTransaction = new Operation();
private long mResultLong = Long.MIN_VALUE;
private String mResultString;
- OperationLog(SQLiteConnectionPool pool) {
- mPool = pool;
- }
+ private final RingBuffer<Operation> mLongOperations =
+ new RingBuffer<>(()->{return new Operation();},
+ (n) ->{return new Operation[n];},
+ MAX_LONG_OPERATIONS);
+ private int mTotalLongOperations = 0;
+
+ // Limit log messages to one every 5 minutes, except that a burst may be 10 messages long.
+ private final RateLimiter mLongLimiter = new RateLimiter(300_000, 10);
public int beginOperation(String kind, String sql, Object[] bindArgs) {
mResultLong = Long.MIN_VALUE;
mResultString = null;
synchronized (mOperations) {
- final int index = (mIndex + 1) % MAX_RECENT_OPERATIONS;
- Operation operation = mOperations[index];
- if (operation == null) {
- operation = new Operation();
- mOperations[index] = operation;
- } else {
- operation.mFinished = false;
- operation.mException = null;
- if (operation.mBindArgs != null) {
- operation.mBindArgs.clear();
- }
- }
- operation.mStartWallTime = System.currentTimeMillis();
- operation.mStartTime = SystemClock.uptimeMillis();
+ Operation operation = newOperationLocked();
operation.mKind = kind;
operation.mSql = sql;
- operation.mPath = mPool.getPath();
- operation.mResultLong = Long.MIN_VALUE;
- operation.mResultString = null;
if (bindArgs != null) {
if (operation.mBindArgs == null) {
operation.mBindArgs = new ArrayList<Object>();
- } else {
- operation.mBindArgs.clear();
}
for (int i = 0; i < bindArgs.length; i++) {
final Object arg = bindArgs[i];
@@ -1649,16 +1698,45 @@
}
}
}
- operation.mCookie = newOperationCookieLocked(index);
- if (Trace.isTagEnabled(Trace.TRACE_TAG_DATABASE)) {
+ operation.mTraced = Trace.isTagEnabled(Trace.TRACE_TAG_DATABASE);
+ if (operation.mTraced) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_DATABASE, operation.getTraceMethodName(),
operation.mCookie);
}
- mIndex = index;
return operation.mCookie;
}
}
+ public void beginTransaction(String kind) {
+ synchronized (mOperations) {
+ Operation operation = newOperationLocked();
+ operation.mKind = kind;
+ mTransaction.copyFrom(operation);
+
+ if (operation.mTraced) {
+ Trace.asyncTraceBegin(Trace.TRACE_TAG_DATABASE, operation.getTraceMethodName(),
+ operation.mCookie);
+ }
+ }
+ }
+
+ /**
+ * Fetch a new operation from the ring buffer. The operation is properly initialized.
+ * This advances mIndex to point to the next element.
+ */
+ private Operation newOperationLocked() {
+ final int index = (mIndex + 1) % MAX_RECENT_OPERATIONS;
+ Operation operation = mOperations[index];
+ if (operation == null) {
+ mOperations[index] = new Operation();
+ operation = mOperations[index];
+ }
+ operation.start();
+ operation.mCookie = newOperationCookieLocked(index);
+ mIndex = index;
+ return operation;
+ }
+
public void failOperation(int cookie, Exception ex) {
synchronized (mOperations) {
final Operation operation = getOperationLocked(cookie);
@@ -1682,6 +1760,20 @@
}
}
+ public boolean endTransaction(boolean success) {
+ synchronized (mOperations) {
+ mTransaction.mResultLong = success ? 1 : 0;
+ final long execTime = finishOperationLocked(mTransaction);
+ final Operation operation = getOperationLocked(mTransaction.mCookie);
+ if (operation != null) {
+ operation.copyFrom(mTransaction);
+ }
+ mTransaction.setEmpty();
+ return NoPreloadHolder.DEBUG_LOG_SLOW_QUERIES
+ && SQLiteDebug.shouldLogSlowQuery(execTime);
+ }
+ }
+
public void logOperation(int cookie, String detail) {
synchronized (mOperations) {
logOperationLocked(cookie, detail);
@@ -1699,13 +1791,11 @@
private boolean endOperationDeferLogLocked(int cookie) {
final Operation operation = getOperationLocked(cookie);
if (operation != null) {
- if (Trace.isTagEnabled(Trace.TRACE_TAG_DATABASE)) {
+ if (operation.mTraced) {
Trace.asyncTraceEnd(Trace.TRACE_TAG_DATABASE, operation.getTraceMethodName(),
operation.mCookie);
}
- operation.mEndTime = SystemClock.uptimeMillis();
- operation.mFinished = true;
- final long execTime = operation.mEndTime - operation.mStartTime;
+ final long execTime = finishOperationLocked(operation);
mPool.onStatementExecuted(execTime);
return NoPreloadHolder.DEBUG_LOG_SLOW_QUERIES && SQLiteDebug.shouldLogSlowQuery(
execTime);
@@ -1730,10 +1820,25 @@
return generation << COOKIE_GENERATION_SHIFT | index;
}
+ /** Close out the operation and return the elapsed time. */
+ private long finishOperationLocked(Operation operation) {
+ operation.mEndTime = SystemClock.uptimeMillis();
+ operation.mFinished = true;
+ final long elapsed = operation.mEndTime - operation.mStartTime;
+ if (elapsed > LONG_OPERATION_THRESHOLD_MS) {
+ mLongOperations.getNextSlot().copyFrom(operation);
+ mTotalLongOperations++;
+ if (mLongLimiter.tryAcquire()) {
+ Log.i(TAG, "Long db operation: " + mConfiguration.label);
+ }
+ }
+ return elapsed;
+ }
+
private Operation getOperationLocked(int cookie) {
final int index = cookie & COOKIE_INDEX_MASK;
final Operation operation = mOperations[index];
- return operation.mCookie == cookie ? operation : null;
+ return (operation != null && operation.mCookie == cookie) ? operation : null;
}
public String describeCurrentOperation() {
@@ -1748,48 +1853,87 @@
}
}
- public void dump(Printer printer) {
+ /**
+ * Dump an Operation if it is not in the recent operations list. Return 1 if the
+ * operation was dumped and 0 if not.
+ */
+ private int dumpIfNotRecentLocked(Printer pw, Operation op, int counter) {
+ if (op == null || op.isEmpty() || getOperationLocked(op.mCookie) != null) {
+ return 0;
+ }
+ pw.println(op.describe(counter));
+ return 1;
+ }
+
+ private void dumpRecentLocked(Printer printer) {
synchronized (mOperations) {
printer.println(" Most recently executed operations:");
int index = mIndex;
- Operation operation = mOperations[index];
- if (operation != null) {
- // Note: SimpleDateFormat is not thread-safe, cannot be compile-time created,
- // and is relatively expensive to create during preloading. This method is only
- // used when dumping a connection, which is a rare (mainly error) case.
- SimpleDateFormat opDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
- int n = 0;
- do {
- StringBuilder msg = new StringBuilder();
- msg.append(" ").append(n).append(": [");
- String formattedStartTime = opDF.format(new Date(operation.mStartWallTime));
- msg.append(formattedStartTime);
- msg.append("] ");
- operation.describe(msg, false); // Never dump bingargs in a bugreport
- printer.println(msg.toString());
-
- if (index > 0) {
- index -= 1;
- } else {
- index = MAX_RECENT_OPERATIONS - 1;
- }
- n += 1;
- operation = mOperations[index];
- } while (operation != null && n < MAX_RECENT_OPERATIONS);
- } else {
+ if (index == 0) {
printer.println(" <none>");
+ return;
}
+
+ // Operations are dumped in order of most recent first.
+ int counter = 0;
+ int n = 0;
+ Operation operation = mOperations[index];
+ do {
+ printer.println(operation.describe(counter));
+
+ if (index > 0) {
+ index -= 1;
+ } else {
+ index = MAX_RECENT_OPERATIONS - 1;
+ }
+ n++;
+ counter++;
+ operation = mOperations[index];
+ } while (operation != null && n < MAX_RECENT_OPERATIONS);
+ counter += dumpIfNotRecentLocked(printer, mTransaction, counter);
+ }
+ }
+
+ private void dumpLongLocked(Printer printer) {
+ printer.println(" Operations exceeding " + LONG_OPERATION_THRESHOLD_MS + "ms:");
+ if (mLongOperations.isEmpty()) {
+ printer.println(" <none>");
+ return;
+ }
+ Operation[] longOps = mLongOperations.toArray();
+ for (int i = 0; i < longOps.length; i++) {
+ if (longOps[i] != null) {
+ printer.println(longOps[i].describe(i));
+ }
+ }
+ }
+
+ public long getTotalLongOperations() {
+ return mTotalLongOperations;
+ }
+
+ public void dump(Printer printer) {
+ synchronized (mOperations) {
+ dumpRecentLocked(printer);
+ dumpLongLocked(printer);
}
}
}
- private static final class Operation {
+ private final class Operation {
// Trim all SQL statements to 256 characters inside the trace marker.
// This limit gives plenty of context while leaving space for other
// entries in the trace buffer (and ensures atrace doesn't truncate the
// marker for us, potentially losing metadata in the process).
private static final int MAX_TRACE_METHOD_NAME_LEN = 256;
+ // The reserved start time that indicates the Operation is empty.
+ private static final long EMPTY_OPERATION = -1;
+
+ // The formatter for the timestamp.
+ private static final DateTimeFormatter sDateTime =
+ DateTimeFormatter.ofPattern("MM-dd HH:mm:ss.SSS", Locale.US);
+
public long mStartWallTime; // in System.currentTimeMillis()
public long mStartTime; // in SystemClock.uptimeMillis();
public long mEndTime; // in SystemClock.uptimeMillis();
@@ -1799,16 +1943,61 @@
public boolean mFinished;
public Exception mException;
public int mCookie;
- public String mPath;
public long mResultLong; // MIN_VALUE means "value not set".
public String mResultString;
+ public boolean mTraced;
+
+ /** Reset the object to begin a new operation. */
+ void start() {
+ mStartWallTime = System.currentTimeMillis();
+ mStartTime = SystemClock.uptimeMillis();
+ mEndTime = Long.MIN_VALUE;
+ mKind = null;
+ mSql = null;
+ if (mBindArgs != null) mBindArgs.clear();
+ mFinished = false;
+ mException = null;
+ mCookie = -1;
+ mResultLong = Long.MIN_VALUE;
+ mResultString = null;
+ mTraced = false;
+ }
+
+ /**
+ * Initialize from the source object. This is meant to clone the object for use in a
+ * transaction operation. To that end, the local bind args are set to null.
+ */
+ void copyFrom(Operation r) {
+ mStartWallTime = r.mStartWallTime;
+ mStartTime = r.mStartTime;
+ mEndTime = r.mEndTime;
+ mKind = r.mKind;
+ mSql = r.mSql;
+ mBindArgs = null;
+ mFinished = r.mFinished;
+ mException = r.mException;
+ mCookie = r.mCookie;
+ mResultLong = r.mResultLong;
+ mResultString = r.mResultString;
+ mTraced = r.mTraced;
+ }
+
+ /** Mark the operation empty. */
+ void setEmpty() {
+ mStartWallTime = EMPTY_OPERATION;
+ }
+
+ /** Return true if the operation is empty. */
+ boolean isEmpty() {
+ return mStartWallTime == EMPTY_OPERATION;
+ }
public void describe(StringBuilder msg, boolean allowDetailedLog) {
msg.append(mKind);
if (mFinished) {
msg.append(" took ").append(mEndTime - mStartTime).append("ms");
} else {
- msg.append(" started ").append(System.currentTimeMillis() - mStartWallTime)
+ msg.append(" started ").append(SystemClock.uptimeMillis() - mStartTime)
.append("ms ago");
}
msg.append(" - ").append(getStatus());
@@ -1837,7 +2026,7 @@
}
msg.append("]");
}
- msg.append(", path=").append(mPath);
+ msg.append(", path=").append(mPool.getPath());
if (mException != null) {
msg.append(", exception=\"").append(mException.getMessage()).append("\"");
}
@@ -1849,6 +2038,21 @@
}
}
+ /**
+ * Convert a wall-clock time in milliseconds to logcat format.
+ */
+ private String timeString(long millis) {
+ return sDateTime.withZone(ZoneId.systemDefault()).format(Instant.ofEpochMilli(millis));
+ }
+
+ public String describe(int n) {
+ final StringBuilder msg = new StringBuilder();
+ final String start = timeString(mStartWallTime);
+ msg.append(" ").append(n).append(": [").append(start).append("] ");
+ describe(msg, false); // Never dump bindargs in a bugreport
+ return msg.toString();
+ }
+
private String getStatus() {
if (!mFinished) {
return "running";
@@ -1862,7 +2066,6 @@
return methodName.substring(0, MAX_TRACE_METHOD_NAME_LEN);
return methodName;
}
-
}
/**
diff --git a/core/java/android/database/sqlite/SQLiteConnectionPool.java b/core/java/android/database/sqlite/SQLiteConnectionPool.java
index ad335b6..15d7d66 100644
--- a/core/java/android/database/sqlite/SQLiteConnectionPool.java
+++ b/core/java/android/database/sqlite/SQLiteConnectionPool.java
@@ -1175,7 +1175,7 @@
+ ", isLegacyCompatibilityWalEnabled=" + isCompatibilityWalEnabled
+ ", journalMode=" + TextUtils.emptyIfNull(mConfiguration.resolveJournalMode())
+ ", syncMode=" + TextUtils.emptyIfNull(mConfiguration.resolveSyncMode()));
- printer.println(" IsReadOnlyDatabase=" + mConfiguration.isReadOnlyDatabase());
+ printer.println(" IsReadOnlyDatabase: " + mConfiguration.isReadOnlyDatabase());
if (isCompatibilityWalEnabled) {
printer.println(" Compatibility WAL enabled: wal_syncmode="
diff --git a/core/java/android/database/sqlite/SQLiteSession.java b/core/java/android/database/sqlite/SQLiteSession.java
index 7d9f02d..3b14d9d 100644
--- a/core/java/android/database/sqlite/SQLiteSession.java
+++ b/core/java/android/database/sqlite/SQLiteSession.java
@@ -312,6 +312,15 @@
cancellationSignal);
}
+ private String modeString(int transactionMode) {
+ switch (transactionMode) {
+ case TRANSACTION_MODE_IMMEDIATE: return "TRANSACTION-IMMEDIATE";
+ case TRANSACTION_MODE_EXCLUSIVE: return "TRANSACTION-EXCLUSIVE";
+ case TRANSACTION_MODE_DEFERRED: return "TRANSACTION-DEFERRED";
+ default: return "TRANSACTION";
+ }
+ }
+
private void beginTransactionUnchecked(int transactionMode,
SQLiteTransactionListener transactionListener, int connectionFlags,
CancellationSignal cancellationSignal) {
@@ -321,6 +330,7 @@
if (mTransactionStack == null) {
acquireConnection(null, connectionFlags, cancellationSignal); // might throw
+ mConnection.recordBeginTransaction(modeString(transactionMode));
}
try {
// Set up the transaction such that we can back out safely
@@ -465,6 +475,7 @@
mConnection.execute("ROLLBACK;", null, cancellationSignal); // might throw
}
} finally {
+ mConnection.recordEndTransaction(successful);
releaseConnection(); // might throw
}
}
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index 42f5fc8..9007b62 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -240,18 +240,19 @@
*
* @param logoDescription The logo description text that will be shown on the prompt.
* @return This builder.
- * @throws IllegalArgumentException If logo description is null or exceeds certain character
- * limit.
+ * @throws IllegalArgumentException If logo description is null.
*/
@FlaggedApi(FLAG_CUSTOM_BIOMETRIC_PROMPT)
@RequiresPermission(SET_BIOMETRIC_DIALOG_ADVANCED)
@NonNull
public BiometricPrompt.Builder setLogoDescription(@NonNull String logoDescription) {
- if (logoDescription == null
- || logoDescription.length() > MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER) {
- throw new IllegalArgumentException(
- "Logo description passed in can not be null or exceed "
- + MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER + " character number.");
+ if (logoDescription == null || logoDescription.isEmpty()) {
+ throw new IllegalArgumentException("Logo description passed in can not be null");
+ }
+ if (logoDescription.length() > MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER) {
+ Log.w(TAG,
+ "Logo description passed in exceeds" + MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER
+ + " character number and may be truncated.");
}
mPromptInfo.setLogoDescription(logoDescription);
return this;
diff --git a/core/java/android/hardware/devicestate/feature/flags.aconfig b/core/java/android/hardware/devicestate/feature/flags.aconfig
index a09c84d..98ba9192 100644
--- a/core/java/android/hardware/devicestate/feature/flags.aconfig
+++ b/core/java/android/hardware/devicestate/feature/flags.aconfig
@@ -17,4 +17,16 @@
description: "Client migration to updated DeviceStateManager API's"
bug: "336640888"
is_fixed_read_only: true
+}
+
+flag {
+ name: "device_state_requester_cancel_state"
+ is_exported: true
+ namespace: "windowing_sdk"
+ description: "Removes foreground requirement if process attempting to cancel a state request is the requester"
+ bug: "354772125"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
}
\ No newline at end of file
diff --git a/core/java/android/hardware/display/BrightnessInfo.java b/core/java/android/hardware/display/BrightnessInfo.java
index c091062..109b0a8 100644
--- a/core/java/android/hardware/display/BrightnessInfo.java
+++ b/core/java/android/hardware/display/BrightnessInfo.java
@@ -60,7 +60,8 @@
@IntDef(prefix = {"BRIGHTNESS_MAX_REASON_"}, value = {
BRIGHTNESS_MAX_REASON_NONE,
BRIGHTNESS_MAX_REASON_THERMAL,
- BRIGHTNESS_MAX_REASON_POWER_IC
+ BRIGHTNESS_MAX_REASON_POWER_IC,
+ BRIGHTNESS_MAX_REASON_WEAR_BEDTIME_MODE
})
@Retention(RetentionPolicy.SOURCE)
public @interface BrightnessMaxReason {}
diff --git a/core/java/android/hardware/input/InputSettings.java b/core/java/android/hardware/input/InputSettings.java
index bec1c9e..d85e41d 100644
--- a/core/java/android/hardware/input/InputSettings.java
+++ b/core/java/android/hardware/input/InputSettings.java
@@ -25,6 +25,7 @@
import static com.android.hardware.input.Flags.keyboardA11yStickyKeysFlag;
import static com.android.hardware.input.Flags.keyboardA11yMouseKeys;
import static com.android.hardware.input.Flags.touchpadTapDragging;
+import static com.android.hardware.input.Flags.touchpadVisualizer;
import static com.android.input.flags.Flags.enableInputFilterRustImpl;
import android.Manifest;
@@ -326,6 +327,15 @@
}
/**
+ * Returns true if the feature flag for touchpad visualizer is enabled.
+ *
+ * @hide
+ */
+ public static boolean isTouchpadVisualizerFeatureFlagEnabled() {
+ return touchpadVisualizer();
+ }
+
+ /**
* Returns true if the touchpad should allow tap dragging.
*
* The returned value only applies to gesture-compatible touchpads.
diff --git a/core/java/android/hardware/input/input_framework.aconfig b/core/java/android/hardware/input/input_framework.aconfig
index b4ad050..6f1d63d8 100644
--- a/core/java/android/hardware/input/input_framework.aconfig
+++ b/core/java/android/hardware/input/input_framework.aconfig
@@ -85,3 +85,10 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "modifier_shortcut_dump"
+ namespace: "input"
+ description: "Dump keyboard shortcuts in dumpsys window"
+ bug: "351963350"
+}
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index e33a5c9..bfff4db 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -29,7 +29,6 @@
import static java.util.Objects.requireNonNull;
import android.annotation.ElapsedRealtimeLong;
-import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
@@ -875,9 +874,10 @@
/*****************************************************************************
* A GenericSoundModel is a specialized {@link SoundModel} for non-voice sound
* patterns.
+ *
+ * @hide
****************************************************************************/
- @FlaggedApi(android.media.soundtrigger.Flags.FLAG_SOUND_TRIGGER_GENERIC_MODEL_API)
- public static final class GenericSoundModel extends SoundModel implements Parcelable {
+ public static class GenericSoundModel extends SoundModel implements Parcelable {
public static final @android.annotation.NonNull Parcelable.Creator<GenericSoundModel> CREATOR
= new Parcelable.Creator<GenericSoundModel>() {
@@ -890,27 +890,12 @@
}
};
- /**
- * Constructor for {@link GenericSoundModel} with version.
- *
- * @param uuid Unique identifier for this sound model.
- * @param vendorUuid Unique vendor identifier for this sound model.
- * @param data Opaque data for this sound model.
- * @param version Vendor-specific version number of this sound model.
- */
public GenericSoundModel(@NonNull UUID uuid, @NonNull UUID vendorUuid,
@Nullable byte[] data, int version) {
- super(uuid, Objects.requireNonNull(vendorUuid, "vendorUuid cannot be null"),
- TYPE_GENERIC_SOUND, data, version);
+ super(uuid, vendorUuid, TYPE_GENERIC_SOUND, data, version);
}
- /**
- * Constructor for {@link GenericSoundModel} without version. The version is set to -1.
- *
- * @param uuid Unique identifier for this sound model.
- * @param vendorUuid Unique vendor identifier for this sound model.
- * @param data Opaque data for this sound model.
- */
+ @UnsupportedAppUsage
public GenericSoundModel(@NonNull UUID uuid, @NonNull UUID vendorUuid,
@Nullable byte[] data) {
this(uuid, vendorUuid, data, -1);
@@ -934,7 +919,7 @@
}
@Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
+ public void writeToParcel(Parcel dest, int flags) {
dest.writeString(getUuid().toString());
if (getVendorUuid() == null) {
dest.writeInt(-1);
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index dd484f6..e039953 100644
--- a/core/java/android/os/BatteryUsageStats.java
+++ b/core/java/android/os/BatteryUsageStats.java
@@ -124,8 +124,8 @@
static final String XML_ATTR_TIME_IN_BACKGROUND = "time_in_background";
static final String XML_ATTR_TIME_IN_FOREGROUND_SERVICE = "time_in_foreground_service";
- // We need about 700 bytes per UID
- private static final long BATTERY_CONSUMER_CURSOR_WINDOW_SIZE = 5_000 * 700;
+ // Max window size. CursorWindow uses only as much memory as needed.
+ private static final long BATTERY_CONSUMER_CURSOR_WINDOW_SIZE = 20_000_000; // bytes
private static final int STATSD_PULL_ATOM_MAX_BYTES = 45000;
diff --git a/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java b/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
index 72b5cf7..da2eec9 100644
--- a/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
+++ b/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.TestApi;
import android.os.Handler;
+import android.os.Looper;
import android.os.Trace;
import android.util.Log;
import android.util.Printer;
@@ -214,7 +215,7 @@
private volatile long mNextInsertSeqValue = 0;
/*
* The exception to the FIFO order rule is sendMessageAtFrontOfQueue().
- * Those messages must be in LIFO order - SIGH.
+ * Those messages must be in LIFO order.
* Decrements on each front of queue insert.
*/
private static final VarHandle sNextFrontInsertSeq;
@@ -535,6 +536,7 @@
/* This is only read/written from the Looper thread */
private int mNextPollTimeoutMillis;
private static final AtomicLong mMessagesDelivered = new AtomicLong();
+ private boolean mMessageDirectlyQueued;
private Message nextMessage() {
int i = 0;
@@ -729,6 +731,7 @@
Binder.flushPendingCommands();
}
+ mMessageDirectlyQueued = false;
nativePollOnce(ptr, mNextPollTimeoutMillis);
Message msg = nextMessage();
@@ -841,6 +844,22 @@
+ node.isAsync() + " now: " + SystemClock.uptimeMillis());
}
+ final Looper myLooper = Looper.myLooper();
+ /* If we are running on the looper thread we can add directly to the priority queue */
+ if (myLooper != null && myLooper.getQueue() == this) {
+ node.removeFromStack();
+ insertIntoPriorityQueue(node);
+ /*
+ * We still need to do this even though we are the current thread,
+ * otherwise next() may sleep indefinitely.
+ */
+ if (!mMessageDirectlyQueued) {
+ mMessageDirectlyQueued = true;
+ nativeWake(mPtr);
+ }
+ return true;
+ }
+
while (true) {
StackNode old = (StackNode) sState.getVolatile(this);
boolean wakeNeeded;
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index e6b1c07..14005b3 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -54,7 +54,6 @@
import android.provider.MediaStore;
import android.system.ErrnoException;
import android.system.Os;
-import android.system.OsConstants;
import android.system.StructStat;
import android.text.TextUtils;
import android.util.DataUnit;
@@ -1535,7 +1534,6 @@
}
/** {@hide} */
- @android.ravenwood.annotation.RavenwoodThrow(blockedBy = OsConstants.class)
public static int translateModeStringToPosix(String mode) {
// Quick check for invalid chars
for (int i = 0; i < mode.length(); i++) {
@@ -1570,7 +1568,6 @@
}
/** {@hide} */
- @android.ravenwood.annotation.RavenwoodThrow(blockedBy = OsConstants.class)
public static String translateModePosixToString(int mode) {
String res = "";
if ((mode & O_ACCMODE) == O_RDWR) {
@@ -1592,7 +1589,6 @@
}
/** {@hide} */
- @android.ravenwood.annotation.RavenwoodThrow(blockedBy = OsConstants.class)
public static int translateModePosixToPfd(int mode) {
int res = 0;
if ((mode & O_ACCMODE) == O_RDWR) {
@@ -1617,7 +1613,6 @@
}
/** {@hide} */
- @android.ravenwood.annotation.RavenwoodThrow(blockedBy = OsConstants.class)
public static int translateModePfdToPosix(int mode) {
int res = 0;
if ((mode & MODE_READ_WRITE) == MODE_READ_WRITE) {
@@ -1642,7 +1637,6 @@
}
/** {@hide} */
- @android.ravenwood.annotation.RavenwoodThrow(blockedBy = OsConstants.class)
public static int translateModeAccessToPosix(int mode) {
if (mode == F_OK) {
// There's not an exact mapping, so we attempt a read-only open to
diff --git a/core/java/android/os/LocaleList.java b/core/java/android/os/LocaleList.java
index d7e440b..c152c2d 100644
--- a/core/java/android/os/LocaleList.java
+++ b/core/java/android/os/LocaleList.java
@@ -37,6 +37,7 @@
* LocaleList is an immutable list of Locales, typically used to keep an ordered list of user
* preferences for locales.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class LocaleList implements Parcelable {
private final Locale[] mList;
// This is a comma-separated list of the locales in the LocaleList created at construction time,
diff --git a/core/java/android/os/LockedMessageQueue/MessageQueue.java b/core/java/android/os/LockedMessageQueue/MessageQueue.java
new file mode 100644
index 0000000..b24e14b
--- /dev/null
+++ b/core/java/android/os/LockedMessageQueue/MessageQueue.java
@@ -0,0 +1,1351 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.os;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.TestApi;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.os.Handler;
+import android.os.Trace;
+import android.util.Log;
+import android.util.Printer;
+import android.util.SparseArray;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.FileDescriptor;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * Low-level class holding the list of messages to be dispatched by a
+ * {@link Looper}. Messages are not added directly to a MessageQueue,
+ * but rather through {@link Handler} objects associated with the Looper.
+ *
+ * <p>You can retrieve the MessageQueue for the current thread with
+ * {@link Looper#myQueue() Looper.myQueue()}.
+ */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
+@android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
+ "com.android.platform.test.ravenwood.nativesubstitution.MessageQueue_host")
+public final class MessageQueue {
+ private static final String TAG = "LockedMessageQueue";
+ private static final boolean DEBUG = false;
+ private static final boolean TRACE = false;
+
+ static final class MessageHeap {
+ static final int MESSAGE_HEAP_INITIAL_SIZE = 16;
+
+ Message[] mHeap = new Message[MESSAGE_HEAP_INITIAL_SIZE];
+ int mNumElements = 0;
+
+ static int parentNodeIdx(int i) {
+ return (i - 1) >>> 1;
+ }
+
+ Message getParentNode(int i) {
+ return mHeap[(i - 1) >>> 1];
+ }
+
+ static int rightNodeIdx(int i) {
+ return 2 * i + 2;
+ }
+
+ Message getRightNode(int i) {
+ return mHeap[2 * i + 2];
+ }
+
+ static int leftNodeIdx(int i) {
+ return 2 * i + 1;
+ }
+
+ Message getLeftNode(int i) {
+ return mHeap[2 * i + 1];
+ }
+
+ int size() {
+ return mHeap.length;
+ }
+
+ int numElements() {
+ return mNumElements;
+ }
+
+ boolean isEmpty() {
+ return mNumElements == 0;
+ }
+
+ Message getMessageAt(int index) {
+ return mHeap[index];
+ }
+
+ /*
+ * Returns:
+ * 0 if x==y.
+ * A value less than 0 if x<y.
+ * A value greater than 0 if x>y.
+ */
+ int compareMessage(Message x, Message y) {
+ int compared = Long.compare(x.when, y.when);
+ if (compared == 0) {
+ compared = Long.compare(x.mInsertSeq, y.mInsertSeq);
+ }
+ return compared;
+ }
+
+ int compareMessageByIdx(int x, int y) {
+ return compareMessage(mHeap[x], mHeap[y]);
+ }
+
+ void swap(int x, int y) {
+ Message tmp = mHeap[x];
+ mHeap[x] = mHeap[y];
+ mHeap[y] = tmp;
+ }
+
+ void siftDown(int i) {
+ int smallest = i;
+ int r, l;
+
+ while (true) {
+ r = rightNodeIdx(i);
+ l = leftNodeIdx(i);
+
+ if (r < mNumElements && compareMessageByIdx(r, smallest) < 0) {
+ smallest = r;
+ }
+
+ if (l < mNumElements && compareMessageByIdx(l, smallest) < 0) {
+ smallest = l;
+ }
+
+ if (smallest != i) {
+ swap(i, smallest);
+ i = smallest;
+ continue;
+ }
+ break;
+ }
+ }
+
+ boolean siftUp(int i) {
+ boolean swapped = false;
+ while (i != 0 && compareMessage(mHeap[i], getParentNode(i)) < 0) {
+ int p = parentNodeIdx(i);
+
+ swap(i, p);
+ swapped = true;
+ i = p;
+ }
+
+ return swapped;
+ }
+
+ void maybeGrowHeap() {
+ if (mNumElements == mHeap.length) {
+ /* Grow by 1.5x */
+ int newSize = mHeap.length + (mHeap.length >>> 1);
+ Message[] newHeap;
+ if (DEBUG) {
+ Log.v(TAG, "maybeGrowHeap mNumElements " + mNumElements + " mHeap.length "
+ + mHeap.length + " newSize " + newSize);
+ }
+
+ newHeap = Arrays.copyOf(mHeap, newSize);
+ mHeap = newHeap;
+ }
+ }
+
+ void add(Message m) {
+ int i;
+
+ maybeGrowHeap();
+
+ i = mNumElements;
+ mNumElements++;
+ mHeap[i] = m;
+
+ siftUp(i);
+ }
+
+ void maybeShrinkHeap() {
+ /* Shrink by 2x */
+ int newSize = mHeap.length >>> 1;
+
+ if (newSize >= MESSAGE_HEAP_INITIAL_SIZE
+ && mNumElements <= newSize) {
+ Message[] newHeap;
+
+ if (DEBUG) {
+ Log.v(TAG, "maybeShrinkHeap mNumElements " + mNumElements + " mHeap.length "
+ + mHeap.length + " newSize " + newSize);
+ }
+
+ newHeap = Arrays.copyOf(mHeap, newSize);
+ mHeap = newHeap;
+ }
+ }
+
+ Message poll() {
+ if (mNumElements > 0) {
+ Message ret = mHeap[0];
+ mNumElements--;
+ mHeap[0] = mHeap[mNumElements];
+ mHeap[mNumElements] = null;
+
+ siftDown(0);
+
+ maybeShrinkHeap();
+ return ret;
+ }
+ return null;
+ }
+
+ Message peek() {
+ if (mNumElements > 0) {
+ return mHeap[0];
+ }
+ return null;
+ }
+
+ private void remove(int i) throws IllegalArgumentException {
+ if (i > mNumElements || mNumElements == 0) {
+ throw new IllegalArgumentException("Index " + i + " out of bounds: "
+ + mNumElements);
+ } else if (i == (mNumElements - 1)) {
+ mHeap[i] = null;
+ mNumElements--;
+ } else {
+ mNumElements--;
+ mHeap[i] = mHeap[mNumElements];
+ mHeap[mNumElements] = null;
+ if (!siftUp(i)) {
+ siftDown(i);
+ }
+ }
+ /* Don't shink here, let the caller do this once it has removed all matching items. */
+ }
+
+ void removeAll() {
+ Message m;
+ for (int i = 0; i < mNumElements; i++) {
+ m = mHeap[i];
+ mHeap[i] = null;
+ m.recycleUnchecked();
+ }
+ mNumElements = 0;
+ maybeShrinkHeap();
+ }
+
+ abstract static class MessageHeapCompare {
+ public abstract boolean compareMessage(Message m, Handler h, int what, Object object,
+ Runnable r, long when);
+ }
+
+ boolean findOrRemoveMessages(Handler h, int what, Object object, Runnable r, long when,
+ MessageHeapCompare compare, boolean removeMatches) {
+ boolean found = false;
+ /*
+ * Walk the heap backwards so we don't have to re-visit an array element due to
+ * sifting
+ */
+ for (int i = mNumElements - 1; i >= 0; i--) {
+ if (compare.compareMessage(mHeap[i], h, what, object, r, when)) {
+ found = true;
+ if (removeMatches) {
+ Message m = mHeap[i];
+ try {
+ remove(i);
+ } catch (IllegalArgumentException e) {
+ Log.wtf(TAG, "Index out of bounds during remove " + e);
+ }
+ m.recycleUnchecked();
+ continue;
+ }
+ break;
+ }
+ }
+ if (found && removeMatches) {
+ maybeShrinkHeap();
+ }
+ return found;
+ }
+
+ /*
+ * Keep this for manual debugging. It's easier to pepper the code with this function
+ * than MessageQueue.dump()
+ */
+ void print() {
+ Log.v(TAG, "heap num elem: " + mNumElements + " mHeap.length " + mHeap.length);
+ for (int i = 0; i < mNumElements; i++) {
+ Log.v(TAG, "[" + i + "]\t" + mHeap[i] + " seq: " + mHeap[i].mInsertSeq + " async: "
+ + mHeap[i].isAsynchronous());
+ }
+ }
+
+ boolean verify(int root) {
+ int r = rightNodeIdx(root);
+ int l = leftNodeIdx(root);
+
+ if (l >= mNumElements && r >= mNumElements) {
+ return true;
+ }
+
+ if (l < mNumElements && compareMessageByIdx(l, root) < 0) {
+ Log.wtf(TAG, "Verify failure: root idx/when: " + root + "/" + mHeap[root].when
+ + " left node idx/when: " + l + "/" + mHeap[l].when);
+ return false;
+ }
+
+ if (r < mNumElements && compareMessageByIdx(r, root) < 0) {
+ Log.wtf(TAG, "Verify failure: root idx/when: " + root + "/" + mHeap[root].when
+ + " right node idx/when: " + r + "/" + mHeap[r].when);
+ return false;
+ }
+
+ if (!verify(r) || !verify(l)) {
+ return false;
+ }
+ return true;
+ }
+
+ boolean checkDanglingReferences(String where) {
+ /* First, let's make sure we didn't leave any dangling references */
+ for (int i = mNumElements; i < mHeap.length; i++) {
+ if (mHeap[i] != null) {
+ Log.wtf(TAG, "[" + where
+ + "] Verify failure: dangling reference found at index "
+ + i + ": " + mHeap[i] + " Async " + mHeap[i].isAsynchronous()
+ + " mNumElements " + mNumElements + " mHeap.length " + mHeap.length);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ boolean verify() {
+ if (!checkDanglingReferences(TAG)) {
+ return false;
+ }
+ return verify(0);
+ }
+ }
+
+ // True if the message queue can be quit.
+ @UnsupportedAppUsage
+ private final boolean mQuitAllowed;
+
+ @UnsupportedAppUsage
+ @SuppressWarnings("unused")
+ private long mPtr; // used by native code
+
+ private final MessageHeap mPriorityQueue = new MessageHeap();
+ private final MessageHeap mAsyncPriorityQueue = new MessageHeap();
+
+ /*
+ * This helps us ensure that messages with the same timestamp are inserted in FIFO order.
+ * Increments on each insert, starting at 0. MessaeHeap.compareMessage() will compare sequences
+ * when delivery timestamps are identical.
+ */
+ private long mNextInsertSeq;
+
+ /*
+ * The exception to the FIFO order rule is sendMessageAtFrontOfQueue().
+ * Those messages must be in LIFO order.
+ * Decrements on each front of queue insert.
+ */
+ private long mNextFrontInsertSeq = -1;
+
+ @UnsupportedAppUsage
+ private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
+ private SparseArray<FileDescriptorRecord> mFileDescriptorRecords;
+ private IdleHandler[] mPendingIdleHandlers;
+ private boolean mQuitting;
+
+ // Indicates whether next() is blocked waiting in pollOnce() with a non-zero timeout.
+ private boolean mBlocked;
+
+ // The next barrier token.
+ // Barriers are indicated by messages with a null target whose arg1 field carries the token.
+ @UnsupportedAppUsage
+ private int mNextBarrierToken;
+
+ private native static long nativeInit();
+ private native static void nativeDestroy(long ptr);
+ @UnsupportedAppUsage
+ private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/
+ private native static void nativeWake(long ptr);
+ private native static boolean nativeIsPolling(long ptr);
+ private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events);
+
+ MessageQueue(boolean quitAllowed) {
+ mQuitAllowed = quitAllowed;
+ mPtr = nativeInit();
+ }
+
+ @GuardedBy("this")
+ private void removeRootFromPriorityQueue(Message msg) {
+ Message tmp;
+ if (msg.isAsynchronous()) {
+ tmp = mAsyncPriorityQueue.poll();
+ } else {
+ tmp = mPriorityQueue.poll();
+ }
+ if (DEBUG && tmp != msg) {
+ Log.wtf(TAG, "Unexpected message at head of heap. Wanted: " + msg + " msg.isAsync "
+ + msg.isAsynchronous() + " Found: " + tmp);
+
+ mPriorityQueue.print();
+ mAsyncPriorityQueue.print();
+ }
+ }
+
+ @GuardedBy("this")
+ private Message pickEarliestMessage(Message x, Message y) {
+ if (x != null && y != null) {
+ if (mPriorityQueue.compareMessage(x, y) < 0) {
+ return x;
+ }
+ return y;
+ }
+
+ return x != null ? x : y;
+ }
+
+ @GuardedBy("this")
+ private Message peekEarliestMessage() {
+ Message x = mPriorityQueue.peek();
+ Message y = mAsyncPriorityQueue.peek();
+
+ return pickEarliestMessage(x, y);
+ }
+
+ @GuardedBy("this")
+ private boolean priorityQueuesAreEmpty() {
+ return mPriorityQueue.isEmpty() && mAsyncPriorityQueue.isEmpty();
+ }
+
+ @GuardedBy("this")
+ private boolean priorityQueueHasBarrier() {
+ Message m = mPriorityQueue.peek();
+
+ if (m != null && m.target == null) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ dispose();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ // Disposes of the underlying message queue.
+ // Must only be called on the looper thread or the finalizer.
+ private void dispose() {
+ if (mPtr != 0) {
+ nativeDestroy(mPtr);
+ mPtr = 0;
+ }
+ }
+
+ /**
+ * Returns true if the looper has no pending messages which are due to be processed.
+ *
+ * <p>This method is safe to call from any thread.
+ *
+ * @return True if the looper is idle.
+ */
+ public boolean isIdle() {
+ synchronized (this) {
+ Message m = peekEarliestMessage();
+ final long now = SystemClock.uptimeMillis();
+
+ return (priorityQueuesAreEmpty() || now < m.when);
+ }
+ }
+
+ /**
+ * Add a new {@link IdleHandler} to this message queue. This may be
+ * removed automatically for you by returning false from
+ * {@link IdleHandler#queueIdle IdleHandler.queueIdle()} when it is
+ * invoked, or explicitly removing it with {@link #removeIdleHandler}.
+ *
+ * <p>This method is safe to call from any thread.
+ *
+ * @param handler The IdleHandler to be added.
+ */
+ public void addIdleHandler(@NonNull IdleHandler handler) {
+ if (handler == null) {
+ throw new NullPointerException("Can't add a null IdleHandler");
+ }
+ synchronized (this) {
+ mIdleHandlers.add(handler);
+ }
+ }
+
+ /**
+ * Remove an {@link IdleHandler} from the queue that was previously added
+ * with {@link #addIdleHandler}. If the given object is not currently
+ * in the idle list, nothing is done.
+ *
+ * <p>This method is safe to call from any thread.
+ *
+ * @param handler The IdleHandler to be removed.
+ */
+ public void removeIdleHandler(@NonNull IdleHandler handler) {
+ synchronized (this) {
+ mIdleHandlers.remove(handler);
+ }
+ }
+
+ /**
+ * Returns whether this looper's thread is currently polling for more work to do.
+ * This is a good signal that the loop is still alive rather than being stuck
+ * handling a callback. Note that this method is intrinsically racy, since the
+ * state of the loop can change before you get the result back.
+ *
+ * <p>This method is safe to call from any thread.
+ *
+ * @return True if the looper is currently polling for events.
+ * @hide
+ */
+ public boolean isPolling() {
+ synchronized (this) {
+ return isPollingLocked();
+ }
+ }
+
+ private boolean isPollingLocked() {
+ // If the loop is quitting then it must not be idling.
+ // We can assume mPtr != 0 when mQuitting is false.
+ return !mQuitting && nativeIsPolling(mPtr);
+ }
+
+ /**
+ * Adds a file descriptor listener to receive notification when file descriptor
+ * related events occur.
+ * <p>
+ * If the file descriptor has already been registered, the specified events
+ * and listener will replace any that were previously associated with it.
+ * It is not possible to set more than one listener per file descriptor.
+ * </p><p>
+ * It is important to always unregister the listener when the file descriptor
+ * is no longer of use.
+ * </p>
+ *
+ * @param fd The file descriptor for which a listener will be registered.
+ * @param events The set of events to receive: a combination of the
+ * {@link OnFileDescriptorEventListener#EVENT_INPUT},
+ * {@link OnFileDescriptorEventListener#EVENT_OUTPUT}, and
+ * {@link OnFileDescriptorEventListener#EVENT_ERROR} event masks. If the requested
+ * set of events is zero, then the listener is unregistered.
+ * @param listener The listener to invoke when file descriptor events occur.
+ *
+ * @see OnFileDescriptorEventListener
+ * @see #removeOnFileDescriptorEventListener
+ */
+ @android.ravenwood.annotation.RavenwoodThrow(blockedBy = android.os.ParcelFileDescriptor.class)
+ public void addOnFileDescriptorEventListener(@NonNull FileDescriptor fd,
+ @OnFileDescriptorEventListener.Events int events,
+ @NonNull OnFileDescriptorEventListener listener) {
+ if (fd == null) {
+ throw new IllegalArgumentException("fd must not be null");
+ }
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+
+ synchronized (this) {
+ updateOnFileDescriptorEventListenerLocked(fd, events, listener);
+ }
+ }
+
+ /**
+ * Removes a file descriptor listener.
+ * <p>
+ * This method does nothing if no listener has been registered for the
+ * specified file descriptor.
+ * </p>
+ *
+ * @param fd The file descriptor whose listener will be unregistered.
+ *
+ * @see OnFileDescriptorEventListener
+ * @see #addOnFileDescriptorEventListener
+ */
+ @android.ravenwood.annotation.RavenwoodThrow(blockedBy = android.os.ParcelFileDescriptor.class)
+ public void removeOnFileDescriptorEventListener(@NonNull FileDescriptor fd) {
+ if (fd == null) {
+ throw new IllegalArgumentException("fd must not be null");
+ }
+
+ synchronized (this) {
+ updateOnFileDescriptorEventListenerLocked(fd, 0, null);
+ }
+ }
+
+ @android.ravenwood.annotation.RavenwoodThrow(blockedBy = android.os.ParcelFileDescriptor.class)
+ private void updateOnFileDescriptorEventListenerLocked(FileDescriptor fd, int events,
+ OnFileDescriptorEventListener listener) {
+ final int fdNum = fd.getInt$();
+
+ int index = -1;
+ FileDescriptorRecord record = null;
+ if (mFileDescriptorRecords != null) {
+ index = mFileDescriptorRecords.indexOfKey(fdNum);
+ if (index >= 0) {
+ record = mFileDescriptorRecords.valueAt(index);
+ if (record != null && record.mEvents == events) {
+ return;
+ }
+ }
+ }
+
+ if (events != 0) {
+ events |= OnFileDescriptorEventListener.EVENT_ERROR;
+ if (record == null) {
+ if (mFileDescriptorRecords == null) {
+ mFileDescriptorRecords = new SparseArray<FileDescriptorRecord>();
+ }
+ record = new FileDescriptorRecord(fd, events, listener);
+ mFileDescriptorRecords.put(fdNum, record);
+ } else {
+ record.mListener = listener;
+ record.mEvents = events;
+ record.mSeq += 1;
+ }
+ nativeSetFileDescriptorEvents(mPtr, fdNum, events);
+ } else if (record != null) {
+ record.mEvents = 0;
+ mFileDescriptorRecords.removeAt(index);
+ nativeSetFileDescriptorEvents(mPtr, fdNum, 0);
+ }
+ }
+
+ // Called from native code.
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ private int dispatchEvents(int fd, int events) {
+ // Get the file descriptor record and any state that might change.
+ final FileDescriptorRecord record;
+ final int oldWatchedEvents;
+ final OnFileDescriptorEventListener listener;
+ final int seq;
+ synchronized (this) {
+ record = mFileDescriptorRecords.get(fd);
+ if (record == null) {
+ return 0; // spurious, no listener registered
+ }
+
+ oldWatchedEvents = record.mEvents;
+ events &= oldWatchedEvents; // filter events based on current watched set
+ if (events == 0) {
+ return oldWatchedEvents; // spurious, watched events changed
+ }
+
+ listener = record.mListener;
+ seq = record.mSeq;
+ }
+
+ // Invoke the listener outside of the lock.
+ int newWatchedEvents = listener.onFileDescriptorEvents(
+ record.mDescriptor, events);
+ if (newWatchedEvents != 0) {
+ newWatchedEvents |= OnFileDescriptorEventListener.EVENT_ERROR;
+ }
+
+ // Update the file descriptor record if the listener changed the set of
+ // events to watch and the listener itself hasn't been updated since.
+ if (newWatchedEvents != oldWatchedEvents) {
+ synchronized (this) {
+ int index = mFileDescriptorRecords.indexOfKey(fd);
+ if (index >= 0 && mFileDescriptorRecords.valueAt(index) == record
+ && record.mSeq == seq) {
+ record.mEvents = newWatchedEvents;
+ if (newWatchedEvents == 0) {
+ mFileDescriptorRecords.removeAt(index);
+ }
+ }
+ }
+ }
+
+ // Return the new set of events to watch for native code to take care of.
+ return newWatchedEvents;
+ }
+
+ private static final AtomicLong mMessagesDelivered = new AtomicLong();
+
+ @UnsupportedAppUsage
+ Message next() {
+ // Return here if the message loop has already quit and been disposed.
+ // This can happen if the application tries to restart a looper after quit
+ // which is not supported.
+ final long ptr = mPtr;
+ if (ptr == 0) {
+ return null;
+ }
+
+ int pendingIdleHandlerCount = -1; // -1 only during first iteration
+ int nextPollTimeoutMillis = 0;
+ for (;;) {
+ if (nextPollTimeoutMillis != 0) {
+ Binder.flushPendingCommands();
+ }
+
+ nativePollOnce(ptr, nextPollTimeoutMillis);
+
+ synchronized (this) {
+ // Try to retrieve the next message. Return if found.
+ final long now = SystemClock.uptimeMillis();
+ Message prevMsg = null;
+ Message msg = peekEarliestMessage();
+
+ if (DEBUG && msg != null) {
+ Log.v(TAG, "Next found message " + msg + " isAsynchronous: "
+ + msg.isAsynchronous() + " target " + msg.target);
+ }
+
+ if (msg != null && !msg.isAsynchronous() && msg.target == null) {
+ // Stalled by a barrier. Find the next asynchronous message in the queue.
+ msg = mAsyncPriorityQueue.peek();
+ if (DEBUG) {
+ Log.v(TAG, "Next message was barrier async msg: " + msg);
+ }
+ }
+
+ if (msg != null) {
+ if (now < msg.when) {
+ // Next message is not ready. Set a timeout to wake up when it is ready.
+ nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
+ } else {
+ mBlocked = false;
+ removeRootFromPriorityQueue(msg);
+ if (DEBUG) Log.v(TAG, "Returning message: " + msg);
+ msg.markInUse();
+ if (TRACE) {
+ Trace.setCounter("MQ.Delivered", mMessagesDelivered.incrementAndGet());
+ }
+ return msg;
+ }
+ } else {
+ // No more messages.
+ nextPollTimeoutMillis = -1;
+ }
+
+ // Process the quit message now that all pending messages have been handled.
+ if (mQuitting) {
+ dispose();
+ return null;
+ }
+
+ // If first time idle, then get the number of idlers to run.
+ // Idle handles only run if the queue is empty or if the first message
+ // in the queue (possibly a barrier) is due to be handled in the future.
+ Message next = peekEarliestMessage();
+ if (pendingIdleHandlerCount < 0
+ && (next == null || now < next.when)) {
+ pendingIdleHandlerCount = mIdleHandlers.size();
+ }
+ if (pendingIdleHandlerCount <= 0) {
+ // No idle handlers to run. Loop and wait some more.
+ mBlocked = true;
+ continue;
+ }
+
+ if (mPendingIdleHandlers == null) {
+ mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
+ }
+ mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
+ }
+
+ // Run the idle handlers.
+ // We only ever reach this code block during the first iteration.
+ for (int i = 0; i < pendingIdleHandlerCount; i++) {
+ final IdleHandler idler = mPendingIdleHandlers[i];
+ mPendingIdleHandlers[i] = null; // release the reference to the handler
+
+ boolean keep = false;
+ try {
+ keep = idler.queueIdle();
+ } catch (Throwable t) {
+ Log.wtf(TAG, "IdleHandler threw exception", t);
+ }
+
+ if (!keep) {
+ synchronized (this) {
+ mIdleHandlers.remove(idler);
+ }
+ }
+ }
+
+ // Reset the idle handler count to 0 so we do not run them again.
+ pendingIdleHandlerCount = 0;
+
+ // While calling an idle handler, a new message could have been delivered
+ // so go back and look again for a pending message without waiting.
+ nextPollTimeoutMillis = 0;
+ }
+ }
+
+ void quit(boolean safe) {
+ if (!mQuitAllowed) {
+ throw new IllegalStateException("Main thread not allowed to quit.");
+ }
+
+ synchronized (this) {
+ if (mQuitting) {
+ return;
+ }
+ mQuitting = true;
+
+ if (safe) {
+ removeAllFutureMessagesLocked();
+ } else {
+ removeAllMessagesLocked();
+ }
+
+ // We can assume mPtr != 0 because mQuitting was previously false.
+ nativeWake(mPtr);
+ }
+ }
+
+ /**
+ * Posts a synchronization barrier to the Looper's message queue.
+ *
+ * Message processing occurs as usual until the message queue encounters the
+ * synchronization barrier that has been posted. When the barrier is encountered,
+ * later synchronous messages in the queue are stalled (prevented from being executed)
+ * until the barrier is released by calling {@link #removeSyncBarrier} and specifying
+ * the token that identifies the synchronization barrier.
+ *
+ * This method is used to immediately postpone execution of all subsequently posted
+ * synchronous messages until a condition is met that releases the barrier.
+ * Asynchronous messages (see {@link Message#isAsynchronous} are exempt from the barrier
+ * and continue to be processed as usual.
+ *
+ * This call must be always matched by a call to {@link #removeSyncBarrier} with
+ * the same token to ensure that the message queue resumes normal operation.
+ * Otherwise the application will probably hang!
+ *
+ * @return A token that uniquely identifies the barrier. This token must be
+ * passed to {@link #removeSyncBarrier} to release the barrier.
+ *
+ * @hide
+ */
+ @UnsupportedAppUsage
+ @TestApi
+ public int postSyncBarrier() {
+ return postSyncBarrier(SystemClock.uptimeMillis());
+ }
+
+ private int postSyncBarrier(long when) {
+ // Enqueue a new sync barrier token.
+ // We don't need to wake the queue because the purpose of a barrier is to stall it.
+ synchronized (this) {
+ final int token = mNextBarrierToken++;
+ final Message msg = Message.obtain();
+ msg.arg1 = token;
+
+ enqueueMessageUnchecked(msg, when);
+ return token;
+ }
+ }
+
+ private class MatchBarrierToken extends MessageHeap.MessageHeapCompare {
+ int mBarrierToken;
+
+ MatchBarrierToken(int token) {
+ super();
+ mBarrierToken = token;
+ }
+
+ @Override
+ public boolean compareMessage(Message m, Handler h, int what, Object object, Runnable r,
+ long when) {
+ if (m.target == null && m.arg1 == mBarrierToken) {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Removes a synchronization barrier.
+ *
+ * @param token The synchronization barrier token that was returned by
+ * {@link #postSyncBarrier}.
+ *
+ * @throws IllegalStateException if the barrier was not found.
+ *
+ * @hide
+ */
+ @UnsupportedAppUsage
+ @TestApi
+ public void removeSyncBarrier(int token) {
+ final MatchBarrierToken matchBarrierToken = new MatchBarrierToken(token);
+
+ // Remove a sync barrier token from the queue.
+ // If the queue is no longer stalled by a barrier then wake it.
+ synchronized (this) {
+ boolean removed;
+ Message first = mPriorityQueue.peek();
+
+ removed = mPriorityQueue.findOrRemoveMessages(null, 0, null, null, 0,
+ matchBarrierToken, true);
+ if (removed && first != null) {
+ // If the loop is quitting then it is already awake.
+ // We can assume mPtr != 0 when mQuitting is false.
+ if (first.target == null && first.arg1 == token && !mQuitting) {
+ nativeWake(mPtr);
+ }
+ } else if (!removed) {
+ throw new IllegalStateException("The specified message queue synchronization "
+ + " barrier token has not been posted or has already been removed.");
+ }
+ }
+ }
+
+ boolean enqueueMessage(Message msg, long when) {
+ if (msg.target == null) {
+ throw new IllegalArgumentException("Message must have a target.");
+ }
+
+ return enqueueMessageUnchecked(msg, when);
+ }
+
+ boolean enqueueMessageUnchecked(Message msg, long when) {
+ synchronized (this) {
+ if (mQuitting) {
+ IllegalStateException e = new IllegalStateException(
+ msg.target + " sending message to a Handler on a dead thread");
+ Log.w(TAG, e.getMessage(), e);
+ msg.recycle();
+ return false;
+ }
+
+ if (msg.isInUse()) {
+ throw new IllegalStateException(msg + " This message is already in use.");
+ }
+
+ msg.markInUse();
+ msg.when = when;
+ msg.mInsertSeq = when != 0 ? mNextInsertSeq++ : mNextFrontInsertSeq--;
+ if (DEBUG) Log.v(TAG, "Enqueue message: " + msg);
+ boolean needWake;
+ boolean isBarrier = msg.target == null;
+ Message first = peekEarliestMessage();
+
+ if (priorityQueuesAreEmpty() || when == 0 || when < first.when) {
+ needWake = mBlocked && !isBarrier;
+ } else {
+ Message firstNonAsyncMessage =
+ first.isAsynchronous() ? mPriorityQueue.peek() : first;
+
+ needWake = mBlocked && firstNonAsyncMessage != null
+ && firstNonAsyncMessage.target == null && msg.isAsynchronous();
+ }
+
+ if (msg.isAsynchronous()) {
+ mAsyncPriorityQueue.add(msg);
+ } else {
+ mPriorityQueue.add(msg);
+ }
+
+ // We can assume mPtr != 0 because mQuitting is false.
+ if (needWake) {
+ nativeWake(mPtr);
+ }
+ }
+ return true;
+ }
+
+ @GuardedBy("this")
+ boolean findOrRemoveMessages(Handler h, int what, Object object, Runnable r, long when,
+ MessageHeap.MessageHeapCompare compare, boolean removeMatches) {
+ boolean found = mPriorityQueue.findOrRemoveMessages(h, what, object, r, when, compare,
+ removeMatches);
+ boolean foundAsync = mAsyncPriorityQueue.findOrRemoveMessages(h, what, object, r, when,
+ compare, removeMatches);
+ return found || foundAsync;
+ }
+
+ private static class MatchHandlerWhatAndObject extends MessageHeap.MessageHeapCompare {
+ @Override
+ public boolean compareMessage(Message m, Handler h, int what, Object object, Runnable r,
+ long when) {
+ if (m.target == h && m.what == what && (object == null || m.obj == object)) {
+ return true;
+ }
+ return false;
+ }
+ }
+ private static final MatchHandlerWhatAndObject sMatchHandlerWhatAndObject =
+ new MatchHandlerWhatAndObject();
+
+ boolean hasMessages(Handler h, int what, Object object) {
+ if (h == null) {
+ return false;
+ }
+
+ synchronized (this) {
+ return findOrRemoveMessages(h, what, object, null, 0, sMatchHandlerWhatAndObject,
+ false);
+ }
+ }
+
+ private static class MatchHandlerWhatAndObjectEquals extends MessageHeap.MessageHeapCompare {
+ @Override
+ public boolean compareMessage(Message m, Handler h, int what, Object object, Runnable r,
+ long when) {
+ if (m.target == h && m.what == what && (object == null || object.equals(m.obj))) {
+ return true;
+ }
+ return false;
+ }
+ }
+ private static final MatchHandlerWhatAndObjectEquals sMatchHandlerWhatAndObjectEquals =
+ new MatchHandlerWhatAndObjectEquals();
+ boolean hasEqualMessages(Handler h, int what, Object object) {
+ if (h == null) {
+ return false;
+ }
+
+ synchronized (this) {
+ return findOrRemoveMessages(h, what, object, null, 0,
+ sMatchHandlerWhatAndObjectEquals, false);
+ }
+ }
+
+ private static class MatchHandlerRunnableAndObject extends MessageHeap.MessageHeapCompare {
+ @Override
+ public boolean compareMessage(Message m, Handler h, int what, Object object, Runnable r,
+ long when) {
+ if (m.target == h && m.callback == r && (object == null || m.obj == object)) {
+ return true;
+ }
+ return false;
+ }
+ }
+ private static final MatchHandlerRunnableAndObject sMatchHandlerRunnableAndObject =
+ new MatchHandlerRunnableAndObject();
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ boolean hasMessages(Handler h, Runnable r, Object object) {
+ if (h == null) {
+ return false;
+ }
+
+ synchronized (this) {
+ return findOrRemoveMessages(h, -1, object, r, 0, sMatchHandlerRunnableAndObject,
+ false);
+ }
+ }
+
+ private static class MatchHandler extends MessageHeap.MessageHeapCompare {
+ @Override
+ public boolean compareMessage(Message m, Handler h, int what, Object object, Runnable r,
+ long when) {
+ if (m.target == h) {
+ return true;
+ }
+ return false;
+ }
+ }
+ private static final MatchHandler sMatchHandler = new MatchHandler();
+ boolean hasMessages(Handler h) {
+ if (h == null) {
+ return false;
+ }
+
+ synchronized (this) {
+ return findOrRemoveMessages(h, -1, null, null, 0, sMatchHandler, false);
+ }
+ }
+
+ void removeMessages(Handler h, int what, Object object) {
+ if (h == null) {
+ return;
+ }
+
+ synchronized (this) {
+ findOrRemoveMessages(h, what, object, null, 0, sMatchHandlerWhatAndObject, true);
+ }
+ }
+
+ void removeEqualMessages(Handler h, int what, Object object) {
+ if (h == null) {
+ return;
+ }
+
+ synchronized (this) {
+ findOrRemoveMessages(h, what, object, null, 0, sMatchHandlerWhatAndObjectEquals, true);
+ }
+ }
+
+ void removeMessages(Handler h, Runnable r, Object object) {
+ if (h == null || r == null) {
+ return;
+ }
+
+ synchronized (this) {
+ findOrRemoveMessages(h, -1, object, r, 0, sMatchHandlerRunnableAndObject, true);
+ }
+ }
+
+ private static class MatchHandlerRunnableAndObjectEquals
+ extends MessageHeap.MessageHeapCompare {
+ @Override
+ public boolean compareMessage(Message m, Handler h, int what, Object object, Runnable r,
+ long when) {
+ if (m.target == h && m.callback == r && (object == null || object.equals(m.obj))) {
+ return true;
+ }
+ return false;
+ }
+ }
+ private static final MatchHandlerRunnableAndObjectEquals sMatchHandlerRunnableAndObjectEquals =
+ new MatchHandlerRunnableAndObjectEquals();
+ void removeEqualMessages(Handler h, Runnable r, Object object) {
+ if (h == null || r == null) {
+ return;
+ }
+
+ synchronized (this) {
+ findOrRemoveMessages(h, -1, object, r, 0, sMatchHandlerRunnableAndObjectEquals, true);
+ }
+ }
+
+ private static class MatchHandlerAndObject extends MessageHeap.MessageHeapCompare {
+ @Override
+ public boolean compareMessage(Message m, Handler h, int what, Object object, Runnable r,
+ long when) {
+ if (m.target == h && (object == null || m.obj == object)) {
+ return true;
+ }
+ return false;
+ }
+ }
+ private static final MatchHandlerAndObject sMatchHandlerAndObject = new MatchHandlerAndObject();
+ void removeCallbacksAndMessages(Handler h, Object object) {
+ if (h == null) {
+ return;
+ }
+
+ synchronized (this) {
+ findOrRemoveMessages(h, -1, object, null, 0, sMatchHandlerAndObject, true);
+ }
+ }
+
+ private static class MatchHandlerAndObjectEquals extends MessageHeap.MessageHeapCompare {
+ @Override
+ public boolean compareMessage(Message m, Handler h, int what, Object object, Runnable r,
+ long when) {
+ if (m.target == h && (object == null || object.equals(m.obj))) {
+ return true;
+ }
+ return false;
+ }
+ }
+ private static final MatchHandlerAndObjectEquals sMatchHandlerAndObjectEquals =
+ new MatchHandlerAndObjectEquals();
+ void removeCallbacksAndEqualMessages(Handler h, Object object) {
+ if (h == null) {
+ return;
+ }
+
+ synchronized (this) {
+ findOrRemoveMessages(h, -1, object, null, 0, sMatchHandlerAndObjectEquals, true);
+ }
+ }
+
+ @GuardedBy("this")
+ private void removeAllMessagesLocked() {
+ mPriorityQueue.removeAll();
+ mAsyncPriorityQueue.removeAll();
+ }
+
+ private static class MatchAllFutureMessages extends MessageHeap.MessageHeapCompare {
+ @Override
+ public boolean compareMessage(Message m, Handler h, int what, Object object, Runnable r,
+ long when) {
+ if (m.when > when) {
+ return true;
+ }
+ return false;
+ }
+ }
+ private static final MatchAllFutureMessages sMatchAllFutureMessages =
+ new MatchAllFutureMessages();
+ @GuardedBy("this")
+ private void removeAllFutureMessagesLocked() {
+ findOrRemoveMessages(null, -1, null, null, SystemClock.uptimeMillis(),
+ sMatchAllFutureMessages, true);
+ }
+
+ int dumpPriorityQueue(Printer pw, String prefix, Handler h, MessageHeap priorityQueue) {
+ int n = 0;
+ long now = SystemClock.uptimeMillis();
+ for (int i = 0; i < priorityQueue.numElements(); i++) {
+ Message m = priorityQueue.getMessageAt(i);
+ if (h == null && h == m.target) {
+ pw.println(prefix + "Message " + n + ": " + m.toString(now));
+ n++;
+ }
+ }
+ return n;
+ }
+
+ void dumpPriorityQueue(ProtoOutputStream proto, MessageHeap priorityQueue) {
+ for (int i = 0; i < priorityQueue.numElements(); i++) {
+ Message m = priorityQueue.getMessageAt(i);
+ m.dumpDebug(proto, MessageQueueProto.MESSAGES);
+ }
+ }
+
+ void dump(Printer pw, String prefix, Handler h) {
+ synchronized (this) {
+ pw.println(prefix + "(MessageQueue is using Locked implementation)");
+ long now = SystemClock.uptimeMillis();
+ int n = dumpPriorityQueue(pw, prefix, h, mPriorityQueue);
+ n += dumpPriorityQueue(pw, prefix, h, mAsyncPriorityQueue);
+ pw.println(prefix + "(Total messages: " + n + ", polling=" + isPollingLocked()
+ + ", quitting=" + mQuitting + ")");
+ }
+ }
+
+ void dumpDebug(ProtoOutputStream proto, long fieldId) {
+ final long messageQueueToken = proto.start(fieldId);
+ synchronized (this) {
+ dumpPriorityQueue(proto, mPriorityQueue);
+ dumpPriorityQueue(proto, mAsyncPriorityQueue);
+ proto.write(MessageQueueProto.IS_POLLING_LOCKED, isPollingLocked());
+ proto.write(MessageQueueProto.IS_QUITTING, mQuitting);
+ }
+ proto.end(messageQueueToken);
+ }
+
+ /**
+ * Callback interface for discovering when a thread is going to block
+ * waiting for more messages.
+ */
+ public static interface IdleHandler {
+ /**
+ * Called when the message queue has run out of messages and will now
+ * wait for more. Return true to keep your idle handler active, false
+ * to have it removed. This may be called if there are still messages
+ * pending in the queue, but they are all scheduled to be dispatched
+ * after the current time.
+ */
+ boolean queueIdle();
+ }
+
+ /**
+ * A listener which is invoked when file descriptor related events occur.
+ */
+ public interface OnFileDescriptorEventListener {
+ /**
+ * File descriptor event: Indicates that the file descriptor is ready for input
+ * operations, such as reading.
+ * <p>
+ * The listener should read all available data from the file descriptor
+ * then return <code>true</code> to keep the listener active or <code>false</code>
+ * to remove the listener.
+ * </p><p>
+ * In the case of a socket, this event may be generated to indicate
+ * that there is at least one incoming connection that the listener
+ * should accept.
+ * </p><p>
+ * This event will only be generated if the {@link #EVENT_INPUT} event mask was
+ * specified when the listener was added.
+ * </p>
+ */
+ public static final int EVENT_INPUT = 1 << 0;
+
+ /**
+ * File descriptor event: Indicates that the file descriptor is ready for output
+ * operations, such as writing.
+ * <p>
+ * The listener should write as much data as it needs. If it could not
+ * write everything at once, then it should return <code>true</code> to
+ * keep the listener active. Otherwise, it should return <code>false</code>
+ * to remove the listener then re-register it later when it needs to write
+ * something else.
+ * </p><p>
+ * This event will only be generated if the {@link #EVENT_OUTPUT} event mask was
+ * specified when the listener was added.
+ * </p>
+ */
+ public static final int EVENT_OUTPUT = 1 << 1;
+
+ /**
+ * File descriptor event: Indicates that the file descriptor encountered a
+ * fatal error.
+ * <p>
+ * File descriptor errors can occur for various reasons. One common error
+ * is when the remote peer of a socket or pipe closes its end of the connection.
+ * </p><p>
+ * This event may be generated at any time regardless of whether the
+ * {@link #EVENT_ERROR} event mask was specified when the listener was added.
+ * </p>
+ */
+ public static final int EVENT_ERROR = 1 << 2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "EVENT_" }, value = {
+ EVENT_INPUT,
+ EVENT_OUTPUT,
+ EVENT_ERROR
+ })
+ public @interface Events {}
+
+ /**
+ * Called when a file descriptor receives events.
+ *
+ * @param fd The file descriptor.
+ * @param events The set of events that occurred: a combination of the
+ * {@link #EVENT_INPUT}, {@link #EVENT_OUTPUT}, and {@link #EVENT_ERROR} event masks.
+ * @return The new set of events to watch, or 0 to unregister the listener.
+ *
+ * @see #EVENT_INPUT
+ * @see #EVENT_OUTPUT
+ * @see #EVENT_ERROR
+ */
+ @Events int onFileDescriptorEvents(@NonNull FileDescriptor fd, @Events int events);
+ }
+
+ private static final class FileDescriptorRecord {
+ public final FileDescriptor mDescriptor;
+ public int mEvents;
+ public OnFileDescriptorEventListener mListener;
+ public int mSeq;
+
+ public FileDescriptorRecord(FileDescriptor descriptor,
+ int events, OnFileDescriptorEventListener listener) {
+ mDescriptor = descriptor;
+ mEvents = events;
+ mListener = listener;
+ }
+ }
+}
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index 161951e..a1db9be 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -126,6 +126,10 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public long when;
+ /** @hide */
+ @SuppressWarnings("unused")
+ public long mInsertSeq;
+
/*package*/ Bundle data;
@UnsupportedAppUsage
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index 6d6757d5..7d3076d 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -106,6 +106,9 @@
# ProfilingService
per-file ProfilingServiceManager.java = file:/PERFORMANCE_OWNERS
+# Performance
+per-file IpcDataCache.java = file:/PERFORMANCE_OWNERS
+
# Memory
per-file OomKillRecord.java = file:/MEMORY_OWNERS
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 464df23..4cc057a 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -340,7 +340,6 @@
return pfd;
}
- @RavenwoodReplace
private static FileDescriptor openInternal(File file, int mode) throws FileNotFoundException {
if ((mode & MODE_WRITE_ONLY) != 0 && (mode & MODE_APPEND) == 0
&& (mode & MODE_TRUNCATE) == 0 && ((mode & MODE_READ_ONLY) == 0)
@@ -364,26 +363,16 @@
}
}
- private static FileDescriptor openInternal$ravenwood(File file, int mode)
- throws FileNotFoundException {
- try {
- return native_open$ravenwood(file, mode);
- } catch (FileNotFoundException e) {
- throw e;
- } catch (IOException e) {
- throw new FileNotFoundException(e.getMessage());
- }
- }
-
@RavenwoodReplace
private static void closeInternal(FileDescriptor fd) {
IoUtils.closeQuietly(fd);
}
private static void closeInternal$ravenwood(FileDescriptor fd) {
- // Desktop JVM doesn't have FileDescriptor.close(), so we'll need to go to the ravenwood
- // side to close it.
- native_close$ravenwood(fd);
+ try {
+ Os.close(fd);
+ } catch (ErrnoException ignored) {
+ }
}
/**
@@ -743,7 +732,6 @@
* Return the total size of the file representing this fd, as determined by
* {@code stat()}. Returns -1 if the fd is not a file.
*/
- @RavenwoodThrow(reason = "Os.readlink() and Os.stat()")
public long getStatSize() {
if (mWrapped != null) {
return mWrapped.getStatSize();
@@ -1277,32 +1265,19 @@
}
}
- // These native methods are currently only implemented by Ravenwood, as it's the only
- // mechanism we have to jump to our RavenwoodNativeSubstitutionClass
- private static native void native_setFdInt$ravenwood(FileDescriptor fd, int fdInt);
- private static native int native_getFdInt$ravenwood(FileDescriptor fd);
- private static native FileDescriptor native_open$ravenwood(File file, int pfdMode)
- throws IOException;
- private static native void native_close$ravenwood(FileDescriptor fd);
+ private static native void setFdInt$ravenwood(FileDescriptor fd, int fdInt);
+ private static native int getFdInt$ravenwood(FileDescriptor fd);
@RavenwoodReplace
private static void setFdInt(FileDescriptor fd, int fdInt) {
fd.setInt$(fdInt);
}
- private static void setFdInt$ravenwood(FileDescriptor fd, int fdInt) {
- native_setFdInt$ravenwood(fd, fdInt);
- }
-
@RavenwoodReplace
private static int getFdInt(FileDescriptor fd) {
return fd.getInt$();
}
- private static int getFdInt$ravenwood(FileDescriptor fd) {
- return native_getFdInt$ravenwood(fd);
- }
-
@RavenwoodReplace
private void setFdOwner(FileDescriptor fd) {
IoUtils.setFdOwner(fd, this);
@@ -1320,7 +1295,6 @@
private int acquireRawFd$ravenwood(FileDescriptor fd) {
// FD owners currently unsupported under Ravenwood; return FD directly
return getFdInt(fd);
-
}
@RavenwoodReplace
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index ce3156e..1fb7937 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -139,11 +139,16 @@
* @param screenState The overridden screen state, or {@link Display#STATE_UNKNOWN}
* to disable the override.
* @param reason The reason for overriding the screen state.
- * @param screenBrightness The overridden screen brightness, or
- * {@link PowerManager#BRIGHTNESS_DEFAULT} to disable the override.
+ * @param screenBrightnessFloat The overridden screen brightness between
+ * {@link PowerManager#BRIGHTNESS_MIN} and {@link PowerManager#BRIGHTNESS_MAX}, or
+ * {@link PowerManager#BRIGHTNESS_INVALID_FLOAT} if screenBrightnessInt should be used instead.
+ * @param screenBrightnessInt The overridden screen brightness between 1 and 255, or
+ * {@link PowerManager#BRIGHTNESS_DEFAULT} to disable the override. Not used if
+ * screenBrightnessFloat is provided (is not NaN).
*/
public abstract void setDozeOverrideFromDreamManager(
- int screenState, @Display.StateReason int reason, int screenBrightness);
+ int screenState, @Display.StateReason int reason, float screenBrightnessFloat,
+ int screenBrightnessInt);
/**
* Used by sidekick manager to tell the power manager if it shouldn't change the display state
diff --git a/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java b/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java
index 967332f..79f229a 100644
--- a/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java
+++ b/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java
@@ -209,7 +209,7 @@
private volatile long mNextInsertSeqValue = 0;
/*
* The exception to the FIFO order rule is sendMessageAtFrontOfQueue().
- * Those messages must be in LIFO order - SIGH.
+ * Those messages must be in LIFO order.
* Decrements on each front of queue insert.
*/
private static final VarHandle sNextFrontInsertSeq;
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 475984e..f3ef9e1 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -1024,6 +1024,7 @@
new Creator<Composed>() {
@Override
public Composed createFromParcel(Parcel in) {
+ in.readInt(); // Skip the parcel type token
return new Composed(in);
}
@@ -1298,6 +1299,7 @@
new Creator<VendorEffect>() {
@Override
public VendorEffect createFromParcel(Parcel in) {
+ in.readInt(); // Skip the parcel type token
return new VendorEffect(in);
}
diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig
index 5ef597d..3fe063d 100644
--- a/core/java/android/permission/flags.aconfig
+++ b/core/java/android/permission/flags.aconfig
@@ -91,6 +91,8 @@
bug: "283989236"
}
+# This flag is enabled since V but not a MUST requirement in CDD yet, so it needs to stay around
+# for now and any code working with it should keep checking the flag.
flag {
name: "signature_permission_allowlist_enabled"
is_fixed_read_only: true
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index c186538..5703f69 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5912,6 +5912,14 @@
public static final String SHOW_KEY_PRESSES = "show_key_presses";
/**
+ * Show touchpad input visualization on screen.
+ * 0 = no
+ * 1 = yes
+ * @hide
+ */
+ public static final String TOUCHPAD_VISUALIZER = "touchpad_visualizer";
+
+ /**
* Show rotary input dispatched to focused windows on the screen.
* 0 = no
* 1 = yes
@@ -15820,7 +15828,7 @@
* The following keys are supported:
*
* <pre>
- * screen_brightness_array (int[])
+ * screen_brightness_array (int[], values in range [1, 255])
* dimming_scrim_array (int[])
* prox_screen_off_delay (long)
* prox_cooldown_trigger (long)
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 74545a8..06e53ac 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -74,6 +74,7 @@
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.util.DumpUtils;
import java.io.FileDescriptor;
@@ -269,6 +270,7 @@
private volatile int mDozeScreenState = Display.STATE_UNKNOWN;
private volatile @Display.StateReason int mDozeScreenStateReason = Display.STATE_REASON_UNKNOWN;
private volatile int mDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
+ private volatile float mDozeScreenBrightnessFloat = PowerManager.BRIGHTNESS_INVALID_FLOAT;
private boolean mDebug = false;
@@ -927,12 +929,12 @@
try {
if (startAndStopDozingInBackground()) {
mDreamManager.startDozingOneway(
- mDreamToken, mDozeScreenState, mDozeScreenStateReason,
- mDozeScreenBrightness);
+ mDreamToken, mDozeScreenState, mDozeScreenStateReason,
+ mDozeScreenBrightnessFloat, mDozeScreenBrightness);
} else {
mDreamManager.startDozing(
mDreamToken, mDozeScreenState, mDozeScreenStateReason,
- mDozeScreenBrightness);
+ mDozeScreenBrightnessFloat, mDozeScreenBrightness);
}
} catch (RemoteException ex) {
@@ -1057,7 +1059,7 @@
* Gets the screen brightness to use while dozing.
*
* @return The screen brightness while dozing as a value between
- * {@link PowerManager#BRIGHTNESS_OFF} (0) and {@link PowerManager#BRIGHTNESS_ON} (255),
+ * {@link PowerManager#BRIGHTNESS_OFF + 1} (1) and {@link PowerManager#BRIGHTNESS_ON} (255),
* or {@link PowerManager#BRIGHTNESS_DEFAULT} (-1) to ask the system to apply
* its default policy based on the screen state.
*
@@ -1078,11 +1080,11 @@
* The dream may set a different brightness before starting to doze and may adjust
* the brightness while dozing to conserve power and achieve various effects.
* </p><p>
- * Note that dream may specify any brightness in the full 0-255 range, including
+ * Note that dream may specify any brightness in the full 1-255 range, including
* values that are less than the minimum value for manual screen brightness
- * adjustments by the user. In particular, the value may be set to 0 which may
- * turn off the backlight entirely while still leaving the screen on although
- * this behavior is device dependent and not guaranteed.
+ * adjustments by the user. In particular, the value may be set to
+ * {@link PowerManager.BRIGHTNESS_OFF} which may turn off the backlight entirely while still
+ * leaving the screen on although this behavior is device dependent and not guaranteed.
* </p><p>
* The available range of display brightness values and their behavior while dozing is
* hardware dependent and may vary across devices. The dream may therefore
@@ -1090,7 +1092,7 @@
* </p>
*
* @param brightness The screen brightness while dozing as a value between
- * {@link PowerManager#BRIGHTNESS_OFF} (0) and {@link PowerManager#BRIGHTNESS_ON} (255),
+ * {@link PowerManager#BRIGHTNESS_OFF + 1} (1) and {@link PowerManager#BRIGHTNESS_ON} (255),
* or {@link PowerManager#BRIGHTNESS_DEFAULT} (-1) to ask the system to apply
* its default policy based on the screen state.
*
@@ -1108,6 +1110,44 @@
}
/**
+ * Sets the screen brightness to use while dozing.
+ * <p>
+ * The value of this property determines the power state of the primary display
+ * once {@link #startDozing} has been called. The default value is
+ * {@link PowerManager#BRIGHTNESS_INVALID_FLOAT} which lets the system decide.
+ * The dream may set a different brightness before starting to doze and may adjust
+ * the brightness while dozing to conserve power and achieve various effects.
+ * </p><p>
+ * Note that dream may specify any brightness in the full 0-1 range, including
+ * values that are less than the minimum value for manual screen brightness
+ * adjustments by the user. In particular, the value may be set to
+ * {@link PowerManager#BRIGHTNESS_OFF_FLOAT} which may turn off the backlight entirely while
+ * still leaving the screen on although this behavior is device dependent and not guaranteed.
+ * </p><p>
+ * The available range of display brightness values and their behavior while dozing is
+ * hardware dependent and may vary across devices. The dream may therefore
+ * need to be modified or configured to correctly support the hardware.
+ * </p>
+ *
+ * @param brightness The screen brightness while dozing as a value between
+ * {@link PowerManager#BRIGHTNESS_MIN} (0) and {@link PowerManager#BRIGHTNESS_MAX} (1),
+ * or {@link PowerManager#BRIGHTNESS_INVALID_FLOAT} (Float.NaN) to ask the system to apply
+ * its default policy based on the screen state.
+ *
+ * @hide For use by system UI components only.
+ */
+ @UnsupportedAppUsage
+ public void setDozeScreenBrightnessFloat(float brightness) {
+ if (!Float.isNaN(brightness)) {
+ brightness = clampAbsoluteBrightnessFloat(brightness);
+ }
+ if (!BrightnessSynchronizer.floatEquals(mDozeScreenBrightnessFloat, brightness)) {
+ mDozeScreenBrightnessFloat = brightness;
+ updateDoze();
+ }
+ }
+
+ /**
* Called when this Dream is constructed.
*/
@Override
@@ -1751,6 +1791,13 @@
return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
}
+ private static float clampAbsoluteBrightnessFloat(float value) {
+ if (value == PowerManager.BRIGHTNESS_OFF_FLOAT) {
+ return value;
+ }
+ return MathUtils.constrain(value, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX);
+ }
+
/**
* The DreamServiceWrapper is used as a gateway to the system_server, where DreamController
* uses it to control the DreamService. It is also used to receive callbacks from the
diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl
index 76f6363..611e791 100644
--- a/core/java/android/service/dreams/IDreamManager.aidl
+++ b/core/java/android/service/dreams/IDreamManager.aidl
@@ -42,7 +42,8 @@
/** @deprecated Please use finishSelfOneway instead. */
void finishSelf(in IBinder token, boolean immediate);
/** @deprecated Please use startDozingOneway instead. */
- void startDozing(in IBinder token, int screenState, int reason, int screenBrightness);
+ void startDozing(in IBinder token, int screenState, int reason, float screenBrightnessFloat,
+ int screenBrightnessInt);
void stopDozing(in IBinder token);
void forceAmbientDisplayEnabled(boolean enabled);
ComponentName[] getDreamComponentsForUser(int userId);
@@ -52,6 +53,7 @@
void startDreamActivity(in Intent intent);
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE)")
oneway void setDreamIsObscured(in boolean isObscured);
- oneway void startDozingOneway(in IBinder token, int screenState, int reason, int screenBrightness);
+ oneway void startDozingOneway(in IBinder token, int screenState, int reason,
+ float screenBrightnessFloat, int screenBrightnessInt);
oneway void finishSelfOneway(in IBinder token, boolean immediate);
}
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index e16a6a1..7ca248d 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -211,6 +211,9 @@
SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
| SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT;
+ private static final int LEGACY_SUPPRESSED_EFFECTS =
+ Policy.SUPPRESSED_EFFECT_SCREEN_ON | Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
+
// ZenModeConfig XML versions distinguishing key changes.
public static final int XML_VERSION_ZEN_UPGRADE = 8;
public static final int XML_VERSION_MODES_API = 11;
@@ -284,6 +287,7 @@
private static final String RULE_ATT_TRIGGER_DESC = "triggerDesc";
private static final String RULE_ATT_DELETION_INSTANT = "deletionInstant";
private static final String RULE_ATT_DISABLED_ORIGIN = "disabledOrigin";
+ private static final String RULE_ATT_LEGACY_SUPPRESSED_EFFECTS = "legacySuppressedEffects";
private static final String DEVICE_EFFECT_DISPLAY_GRAYSCALE = "zdeDisplayGrayscale";
private static final String DEVICE_EFFECT_SUPPRESS_AMBIENT_DISPLAY =
@@ -1171,6 +1175,8 @@
if (Flags.modesUi()) {
rt.disabledOrigin = safeInt(parser, RULE_ATT_DISABLED_ORIGIN,
UPDATE_ORIGIN_UNKNOWN);
+ rt.legacySuppressedEffects = safeInt(parser,
+ RULE_ATT_LEGACY_SUPPRESSED_EFFECTS, 0);
}
}
return rt;
@@ -1228,6 +1234,8 @@
}
if (Flags.modesUi()) {
out.attributeInt(null, RULE_ATT_DISABLED_ORIGIN, rule.disabledOrigin);
+ out.attributeInt(null, RULE_ATT_LEGACY_SUPPRESSED_EFFECTS,
+ rule.legacySuppressedEffects);
}
}
}
@@ -1903,6 +1911,13 @@
ZenPolicy.VISUAL_EFFECT_NOTIFICATION_LIST))) {
suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
}
+
+ // Restore legacy suppressed effects (obsolete fields which are not in ZenPolicy).
+ // These are deprecated and have no effect on behavior, however apps should get them
+ // back if provided to setNotificationPolicy() earlier.
+ suppressedVisualEffects &= ~LEGACY_SUPPRESSED_EFFECTS;
+ suppressedVisualEffects |=
+ (LEGACY_SUPPRESSED_EFFECTS & manualRule.legacySuppressedEffects);
} else {
if (isAllowConversations()) {
priorityCategories |= Policy.PRIORITY_CATEGORY_CONVERSATIONS;
@@ -1996,6 +2011,8 @@
if (policy == null) return;
if (Flags.modesUi()) {
manualRule.zenPolicy = ZenAdapters.notificationPolicyToZenPolicy(policy);
+ manualRule.legacySuppressedEffects =
+ LEGACY_SUPPRESSED_EFFECTS & policy.suppressedVisualEffects;
} else {
setAllowAlarms((policy.priorityCategories & Policy.PRIORITY_CATEGORY_ALARMS) != 0);
allowMedia = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_MEDIA) != 0;
@@ -2521,6 +2538,10 @@
@Nullable public Instant deletionInstant; // Only set on deleted rules.
@FlaggedApi(Flags.FLAG_MODES_UI)
@ConfigChangeOrigin public int disabledOrigin = UPDATE_ORIGIN_UNKNOWN;
+ // The obsolete suppressed effects in NM.Policy (SCREEN_ON, SCREEN_OFF) cannot be put in a
+ // ZenPolicy, so we store them here, only for the manual rule.
+ @FlaggedApi(Flags.FLAG_MODES_UI)
+ int legacySuppressedEffects;
public ZenRule() { }
@@ -2561,6 +2582,7 @@
}
if (Flags.modesUi()) {
disabledOrigin = source.readInt();
+ legacySuppressedEffects = source.readInt();
}
}
}
@@ -2638,6 +2660,7 @@
}
if (Flags.modesUi()) {
dest.writeInt(disabledOrigin);
+ dest.writeInt(legacySuppressedEffects);
}
}
}
@@ -2686,6 +2709,7 @@
}
if (Flags.modesUi()) {
sb.append(",disabledOrigin=").append(disabledOrigin);
+ sb.append(",legacySuppressedEffects=").append(legacySuppressedEffects);
}
}
@@ -2754,7 +2778,8 @@
if (Flags.modesUi()) {
finalEquals = finalEquals
- && other.disabledOrigin == disabledOrigin;
+ && other.disabledOrigin == disabledOrigin
+ && other.legacySuppressedEffects == legacySuppressedEffects;
}
}
@@ -2769,15 +2794,15 @@
component, configurationActivity, pkg, id, enabler, zenPolicy,
zenDeviceEffects, modified, allowManualInvocation, iconResName,
triggerDescription, type, userModifiedFields,
- zenPolicyUserModifiedFields,
- zenDeviceEffectsUserModifiedFields, deletionInstant, disabledOrigin);
+ zenPolicyUserModifiedFields, zenDeviceEffectsUserModifiedFields,
+ deletionInstant, disabledOrigin, legacySuppressedEffects);
} else {
return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition,
component, configurationActivity, pkg, id, enabler, zenPolicy,
zenDeviceEffects, modified, allowManualInvocation, iconResName,
triggerDescription, type, userModifiedFields,
- zenPolicyUserModifiedFields,
- zenDeviceEffectsUserModifiedFields, deletionInstant);
+ zenPolicyUserModifiedFields, zenDeviceEffectsUserModifiedFields,
+ deletionInstant);
}
}
return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition,
diff --git a/core/java/android/service/notification/ZenModeDiff.java b/core/java/android/service/notification/ZenModeDiff.java
index 91ef11c..a37e227 100644
--- a/core/java/android/service/notification/ZenModeDiff.java
+++ b/core/java/android/service/notification/ZenModeDiff.java
@@ -472,6 +472,7 @@
public static final String FIELD_ICON_RES = "iconResName";
public static final String FIELD_TRIGGER_DESCRIPTION = "triggerDescription";
public static final String FIELD_TYPE = "type";
+ public static final String FIELD_LEGACY_SUPPRESSED_EFFECTS = "legacySuppressedEffects";
// NOTE: new field strings must match the variable names in ZenModeConfig.ZenRule
// Special field to track whether this rule became active or inactive
@@ -567,6 +568,13 @@
if (!Objects.equals(from.iconResName, to.iconResName)) {
addField(FIELD_ICON_RES, new FieldDiff<>(from.iconResName, to.iconResName));
}
+ if (android.app.Flags.modesUi()) {
+ if (from.legacySuppressedEffects != to.legacySuppressedEffects) {
+ addField(FIELD_LEGACY_SUPPRESSED_EFFECTS,
+ new FieldDiff<>(from.legacySuppressedEffects,
+ to.legacySuppressedEffects));
+ }
+ }
}
}
diff --git a/core/java/android/service/notification/ZenPolicy.java b/core/java/android/service/notification/ZenPolicy.java
index 910c462..2669391 100644
--- a/core/java/android/service/notification/ZenPolicy.java
+++ b/core/java/android/service/notification/ZenPolicy.java
@@ -1240,7 +1240,10 @@
return "invalidState{" + state + "}";
}
- private String peopleTypeToString(@PeopleType int peopleType) {
+ /**
+ * @hide
+ */
+ public static String peopleTypeToString(@PeopleType int peopleType) {
switch (peopleType) {
case PEOPLE_TYPE_ANYONE:
return "anyone";
diff --git a/core/java/android/view/InputEventAssigner.java b/core/java/android/view/InputEventAssigner.java
index 7fac6c5..30d9aaa 100644
--- a/core/java/android/view/InputEventAssigner.java
+++ b/core/java/android/view/InputEventAssigner.java
@@ -17,7 +17,8 @@
package android.view;
import static android.os.IInputConstants.INVALID_INPUT_EVENT_ID;
-import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
+import static android.view.InputDevice.SOURCE_CLASS_POINTER;
+import static android.view.InputDevice.SOURCE_CLASS_POSITION;
/**
* Process input events and assign input event id to a specific frame.
@@ -64,18 +65,19 @@
public int processEvent(InputEvent event) {
if (event instanceof MotionEvent) {
MotionEvent motionEvent = (MotionEvent) event;
- if (motionEvent.isFromSource(SOURCE_TOUCHSCREEN)) {
+ if (motionEvent.isFromSource(SOURCE_CLASS_POINTER) || motionEvent.isFromSource(
+ SOURCE_CLASS_POSITION)) {
final int action = motionEvent.getActionMasked();
if (action == MotionEvent.ACTION_DOWN) {
mHasUnprocessedDown = true;
mDownEventId = event.getId();
}
- if (mHasUnprocessedDown && action == MotionEvent.ACTION_MOVE) {
- return mDownEventId;
- }
if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
mHasUnprocessedDown = false;
}
+ if (mHasUnprocessedDown) {
+ return mDownEventId;
+ }
}
}
return event.getId();
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index cf329d3..a7641c0 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -4898,5 +4898,4 @@
public static void notifyShutdown() {
nativeNotifyShutdown();
}
-
}
diff --git a/core/java/android/view/SurfaceControlRegistry.java b/core/java/android/view/SurfaceControlRegistry.java
index a806bd2..121c01b 100644
--- a/core/java/android/view/SurfaceControlRegistry.java
+++ b/core/java/android/view/SurfaceControlRegistry.java
@@ -73,7 +73,7 @@
}
// Sort entries by time registered when dumping
// TODO: Or should it sort by name?
- entries.sort((o1, o2) -> (int) (o1.getValue() - o2.getValue()));
+ entries.sort((o1, o2) -> Long.compare(o1.getValue(), o2.getValue()));
final int size = Math.min(entries.size(), limit);
pw.println("SurfaceControlRegistry");
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9e52a14..9518abf 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -145,7 +145,6 @@
import android.annotation.UiContext;
import android.app.ActivityManager;
import android.app.ActivityThread;
-import android.app.ICompatCameraControlCallback;
import android.app.ResourcesManager;
import android.app.WindowConfiguration;
import android.app.compat.CompatChanges;
@@ -516,17 +515,6 @@
int newDisplayId, @Nullable ActivityWindowInfo activityWindowInfo) {
onConfigurationChanged(overrideConfig, newDisplayId);
}
-
- /**
- * Notify the corresponding activity about the request to show or hide a camera compat
- * control for stretched issues in the viewfinder.
- *
- * @param showControl Whether the control should be shown or hidden.
- * @param transformationApplied Whether the treatment is already applied.
- * @param callback The callback executed when the user clicks on a control.
- */
- void requestCompatCameraControl(boolean showControl, boolean transformationApplied,
- ICompatCameraControlCallback callback);
}
/**
@@ -12503,20 +12491,6 @@
}
}
- /**
- * Shows or hides a Camera app compat toggle for stretched issues with the requested state
- * for the corresponding activity.
- *
- * @param showControl Whether the control should be shown or hidden.
- * @param transformationApplied Whether the treatment is already applied.
- * @param callback The callback executed when the user clicks on a control.
- */
- public void requestCompatCameraControl(boolean showControl, boolean transformationApplied,
- ICompatCameraControlCallback callback) {
- mActivityConfigCallback.requestCompatCameraControl(
- showControl, transformationApplied, callback);
- }
-
boolean wasRelayoutRequested() {
return mRelayoutRequested;
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 14978ed..85d4ec0 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -478,6 +478,12 @@
*/
int TRANSIT_SLEEP = 12;
/**
+ * An Activity was going to be visible from back navigation.
+ * @hide
+ */
+ int TRANSIT_PREPARE_BACK_NAVIGATION = 13;
+
+ /**
* The first slot for custom transition types. Callers (like Shell) can make use of custom
* transition types for dealing with special cases. These types are effectively ignored by
* Core and will just be passed along as part of TransitionInfo objects. An example is
@@ -505,6 +511,7 @@
TRANSIT_PIP,
TRANSIT_WAKE,
TRANSIT_SLEEP,
+ TRANSIT_PREPARE_BACK_NAVIGATION,
TRANSIT_FIRST_CUSTOM
})
@Retention(RetentionPolicy.SOURCE)
@@ -1918,6 +1925,7 @@
case TRANSIT_PIP: return "PIP";
case TRANSIT_WAKE: return "WAKE";
case TRANSIT_SLEEP: return "SLEEP";
+ case TRANSIT_PREPARE_BACK_NAVIGATION: return "PREDICTIVE_BACK";
case TRANSIT_FIRST_CUSTOM: return "FIRST_CUSTOM";
default:
if (type > TRANSIT_FIRST_CUSTOM) {
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index 2af935d..09306c7 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -28,7 +28,6 @@
import android.os.SystemProperties;
import android.util.AttributeSet;
import android.util.TypedValue;
-import android.view.WindowInsets;
import dalvik.system.CloseGuard;
@@ -882,13 +881,12 @@
}
/**
- * @return the edges to which outsets can be applied to
+ * @return if a window animation has outsets applied to it.
*
* @hide
*/
- @WindowInsets.Side.InsetsSide
- public int getExtensionEdges() {
- return 0x0;
+ public boolean hasExtension() {
+ return false;
}
/**
diff --git a/core/java/android/view/animation/AnimationSet.java b/core/java/android/view/animation/AnimationSet.java
index bbdc9d0..5aaa994 100644
--- a/core/java/android/view/animation/AnimationSet.java
+++ b/core/java/android/view/animation/AnimationSet.java
@@ -21,7 +21,6 @@
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
-import android.view.WindowInsets;
import java.util.ArrayList;
import java.util.List;
@@ -541,12 +540,12 @@
/** @hide */
@Override
- @WindowInsets.Side.InsetsSide
- public int getExtensionEdges() {
- int edge = 0x0;
+ public boolean hasExtension() {
for (Animation animation : mAnimations) {
- edge |= animation.getExtensionEdges();
+ if (animation.hasExtension()) {
+ return true;
+ }
}
- return edge;
+ return false;
}
}
diff --git a/core/java/android/view/animation/ExtendAnimation.java b/core/java/android/view/animation/ExtendAnimation.java
index ed047c7..210eb8a 100644
--- a/core/java/android/view/animation/ExtendAnimation.java
+++ b/core/java/android/view/animation/ExtendAnimation.java
@@ -20,7 +20,6 @@
import android.content.res.TypedArray;
import android.graphics.Insets;
import android.util.AttributeSet;
-import android.view.WindowInsets;
/**
* An animation that controls the outset of an object.
@@ -51,8 +50,6 @@
private float mToRightValue;
private float mToBottomValue;
- private int mExtensionEdges = 0x0;
-
/**
* Constructor used when an ExtendAnimation is loaded from a resource.
*
@@ -154,22 +151,9 @@
/** @hide */
@Override
- @WindowInsets.Side.InsetsSide
- public int getExtensionEdges() {
- mExtensionEdges = 0x0;
- if (mFromLeftValue > 0 || mToLeftValue > 0) {
- mExtensionEdges |= WindowInsets.Side.LEFT;
- }
- if (mFromRightValue > 0 || mToRightValue > 0) {
- mExtensionEdges |= WindowInsets.Side.RIGHT;
- }
- if (mFromTopValue > 0 || mToTopValue > 0) {
- mExtensionEdges |= WindowInsets.Side.TOP;
- }
- if (mFromBottomValue > 0 || mToBottomValue > 0) {
- mExtensionEdges |= WindowInsets.Side.BOTTOM;
- }
- return mExtensionEdges;
+ public boolean hasExtension() {
+ return mFromInsets.left < 0 || mFromInsets.top < 0 || mFromInsets.right < 0
+ || mFromInsets.bottom < 0;
}
@Override
diff --git a/core/java/android/view/autofill/AutofillClientController.java b/core/java/android/view/autofill/AutofillClientController.java
index 95cae226..abef7cf 100644
--- a/core/java/android/view/autofill/AutofillClientController.java
+++ b/core/java/android/view/autofill/AutofillClientController.java
@@ -94,8 +94,15 @@
* @hide
*/
public boolean isRelayoutFixEnabled() {
+ AutofillManager autofillManager = getAutofillManager();
+ if (autofillManager == null) {
+ if (Helper.sDebug) {
+ Log.d(TAG, "isRelayoutFixEnabled() : getAutofillManager() == null");
+ }
+ return false;
+ }
if (mRelayoutFix == null) {
- mRelayoutFix = getAutofillManager().isRelayoutFixEnabled();
+ mRelayoutFix = autofillManager.isRelayoutFixEnabled();
}
return mRelayoutFix;
}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index d40b72c..4ab6758 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -973,8 +973,12 @@
@GuardedBy("mH")
private void setCurrentRootViewLocked(ViewRootImpl rootView) {
+ final boolean wasEmpty = mCurRootView == null;
mImeDispatcher.switchRootView(mCurRootView, rootView);
mCurRootView = rootView;
+ if (wasEmpty && mCurRootView != null) {
+ mImeDispatcher.updateReceivingDispatcher(mCurRootView.getOnBackInvokedDispatcher());
+ }
}
}
@@ -2949,7 +2953,8 @@
* @param callback Consumer callback that provides {@code true} if view belongs to allowed
* delegate package declared in
* {@link #prepareStylusHandwritingDelegation(View, String)} and handwriting
- * session can start.
+ * session can start. Note: The caller should hold a reference to the callback.
+ * The framework only holds a weak reference.
* @see #prepareStylusHandwritingDelegation(View, String)
* @see #acceptStylusHandwritingDelegation(View)
*/
@@ -2979,7 +2984,8 @@
* @param delegatorPackageName package name of the delegator that handled initial stylus stroke.
* @param flags {@link #HANDWRITING_DELEGATE_FLAG_HOME_DELEGATOR_ALLOWED} or {@code 0}
* @param executor The executor to run the callback on.
- * @param callback {@code true>} would be received if delegation was accepted.
+ * @param callback {@code true} would be received if delegation was accepted. The caller should
+ * hold a reference to the callback. The framework only holds a weak reference.
* @see #prepareStylusHandwritingDelegation(View, String)
* @see #acceptStylusHandwritingDelegation(View)
*/
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 9099db8..ac899f4 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -31,6 +31,7 @@
import static com.android.text.flags.Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE;
import static com.android.text.flags.Flags.FLAG_USE_BOUNDS_FOR_WIDTH;
+import static android.view.inputmethod.Flags.initiationWithoutInputConnection;
import android.R;
import android.annotation.CallSuper;
@@ -2738,6 +2739,8 @@
InputMethodManager imm = getInputMethodManager();
if (imm != null) imm.restartInput(this);
+
+ ensureEditorFocusedNotifiedToHandwritingInitiator();
}
private void setInputTypeFromEditor() {
@@ -7843,6 +7846,20 @@
if (type == InputType.TYPE_NULL && mEditor == null) return; //TYPE_NULL is the default value
createEditorIfNeeded();
mEditor.mInputType = type;
+ ensureEditorFocusedNotifiedToHandwritingInitiator();
+ }
+
+ private void ensureEditorFocusedNotifiedToHandwritingInitiator() {
+ if (!initiationWithoutInputConnection() || isHandwritingDelegate()) {
+ return;
+ }
+ ViewRootImpl viewRoot = getViewRootImpl();
+ if (viewRoot == null) {
+ return;
+ }
+ if (isFocused() && hasWindowFocus() && onCheckIsTextEditor()) {
+ viewRoot.getHandwritingInitiator().onEditorFocused(this);
+ }
}
@Override
diff --git a/core/java/android/window/DisplayWindowPolicyController.java b/core/java/android/window/DisplayWindowPolicyController.java
index 9cd2a71..a16d537 100644
--- a/core/java/android/window/DisplayWindowPolicyController.java
+++ b/core/java/android/window/DisplayWindowPolicyController.java
@@ -23,15 +23,16 @@
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.WindowConfiguration;
-import android.companion.virtualdevice.flags.Flags;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.IntentSender;
import android.content.pm.ActivityInfo;
import android.util.ArraySet;
import java.io.PrintWriter;
import java.util.List;
import java.util.Set;
+import java.util.function.Supplier;
/**
* Abstract class to control the policies of the windows that can be displayed on the virtual
@@ -67,9 +68,7 @@
public DisplayWindowPolicyController() {
synchronized (mSupportedWindowingModes) {
mSupportedWindowingModes.add(WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
- if (Flags.virtualDisplayMultiWindowModeSupport()) {
- mSupportedWindowingModes.add(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW);
- }
+ mSupportedWindowingModes.add(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW);
}
}
@@ -139,10 +138,14 @@
* Returns {@code true} if the given activity can be launched on this virtual display in the
* configuration defined by the rest of the arguments. If the given intent would be intercepted
* by the display owner then this means that the activity cannot be launched.
+ *
+ * The intentSender argument can provide an IntentSender for the original intent to be passed
+ * to any activity listeners, in case the activity cannot be launched.
*/
public abstract boolean canActivityBeLaunched(@NonNull ActivityInfo activityInfo,
@Nullable Intent intent, @WindowConfiguration.WindowingMode int windowingMode,
- int launchingFromDisplayId, boolean isNewTask);
+ int launchingFromDisplayId, boolean isNewTask, boolean isResultExpected,
+ @Nullable Supplier<IntentSender> intentSender);
/**
* Returns {@code true} if the given activity can be launched on this virtual display in the
diff --git a/core/java/android/window/ITaskOrganizerController.aidl b/core/java/android/window/ITaskOrganizerController.aidl
index 478aeec..1748b9d 100644
--- a/core/java/android/window/ITaskOrganizerController.aidl
+++ b/core/java/android/window/ITaskOrganizerController.aidl
@@ -67,7 +67,4 @@
* Restarts the top activity in the given task by killing its process if it is visible.
*/
void restartTaskTopActivityProcessIfVisible(in WindowContainerToken task);
-
- /** Updates a state of camera compat control for stretched issues in the viewfinder. */
- void updateCameraCompatControlState(in WindowContainerToken task, int state);
}
diff --git a/core/java/android/window/ImeOnBackInvokedDispatcher.java b/core/java/android/window/ImeOnBackInvokedDispatcher.java
index ce1f986..771dc7a 100644
--- a/core/java/android/window/ImeOnBackInvokedDispatcher.java
+++ b/core/java/android/window/ImeOnBackInvokedDispatcher.java
@@ -27,10 +27,12 @@
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.util.Log;
+import android.util.Pair;
import android.view.ViewRootImpl;
import com.android.internal.annotations.VisibleForTesting;
+import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.function.Consumer;
@@ -58,7 +60,7 @@
// The handler to run callbacks on. This should be on the same thread
// the ViewRootImpl holding IME's WindowOnBackInvokedDispatcher is created on.
private Handler mHandler;
-
+ private final ArrayDeque<Pair<Integer, Bundle>> mQueuedReceive = new ArrayDeque<>();
public ImeOnBackInvokedDispatcher(Handler handler) {
mResultReceiver = new ResultReceiver(handler) {
@Override
@@ -66,11 +68,22 @@
WindowOnBackInvokedDispatcher dispatcher = getReceivingDispatcher();
if (dispatcher != null) {
receive(resultCode, resultData, dispatcher);
+ } else {
+ mQueuedReceive.add(new Pair<>(resultCode, resultData));
}
}
};
}
+ /** Set receiving dispatcher to consume queued receiving events. */
+ public void updateReceivingDispatcher(@NonNull WindowOnBackInvokedDispatcher dispatcher) {
+ while (!mQueuedReceive.isEmpty()) {
+ final Pair<Integer, Bundle> queuedMessage = mQueuedReceive.poll();
+ receive(queuedMessage.first, queuedMessage.second, dispatcher);
+ }
+ }
+
+
void setHandler(@NonNull Handler handler) {
mHandler = handler;
}
@@ -198,6 +211,7 @@
}
}
mImeCallbacks.clear();
+ mQueuedReceive.clear();
}
@VisibleForTesting(visibility = PACKAGE)
diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java
index b9ffdbc..3ecb619 100644
--- a/core/java/android/window/TaskOrganizer.java
+++ b/core/java/android/window/TaskOrganizer.java
@@ -24,7 +24,6 @@
import android.annotation.SuppressLint;
import android.annotation.TestApi;
import android.app.ActivityManager;
-import android.app.CameraCompatTaskInfo.CameraCompatControlState;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.SurfaceControl;
@@ -252,20 +251,6 @@
}
/**
- * Updates a state of camera compat control for stretched issues in the viewfinder.
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
- public void updateCameraCompatControlState(@NonNull WindowContainerToken task,
- @CameraCompatControlState int state) {
- try {
- mTaskOrganizerController.updateCameraCompatControlState(task, state);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Gets the executor to run callbacks on.
* @hide
*/
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index 91ac4ff..125a0b2 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -31,6 +31,13 @@
}
flag {
+ name: "disable_non_resizable_app_snap_resizing"
+ namespace: "lse_desktop_experience"
+ description: "Stops non-resizable app desktop windows from being snap resized"
+ bug: "325240072"
+}
+
+flag {
name: "enable_desktop_windowing_task_limit"
namespace: "lse_desktop_experience"
description: "Enables a limit on the number of Tasks shown in Desktop Mode"
@@ -192,8 +199,22 @@
}
flag {
+ name: "enable_desktop_windowing_transitions"
+ namespace: "lse_desktop_experience"
+ description: "Enables desktop windowing transition & motion polish changes"
+ bug: "356570693"
+}
+
+flag {
name: "enable_compat_ui_visibility_status"
namespace: "lse_desktop_experience"
description: "Enables the tracking of the status for compat ui elements."
bug: "350953004"
}
+
+flag {
+ name: "enable_desktop_windowing_app_to_web_education"
+ namespace: "lse_desktop_experience"
+ description: "Enables desktop windowing app-to-web education"
+ bug: "348205896"
+}
diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig
index e5a9b6a..d5746e5 100644
--- a/core/java/android/window/flags/windowing_frontend.aconfig
+++ b/core/java/android/window/flags/windowing_frontend.aconfig
@@ -94,14 +94,6 @@
}
flag {
- name: "activity_snapshot_by_default"
- namespace: "systemui"
- description: "Enable record activity snapshot by default"
- bug: "259497289"
- is_fixed_read_only: true
-}
-
-flag {
name: "supports_multi_instance_system_ui"
is_exported: true
namespace: "multitasking"
@@ -201,20 +193,20 @@
}
flag {
- name: "enforce_shell_thread_model"
+ name: "custom_animations_behind_translucent"
namespace: "windowing_frontend"
- description: "Crash the shell process if someone calls in from the wrong thread"
- bug: "351189446"
- is_fixed_read_only: true
+ description: "A change can use its own layer parameters to animate behind a translucent activity"
+ bug: "327332488"
metadata {
purpose: PURPOSE_BUGFIX
}
}
flag {
- name: "custom_animations_behind_translucent"
+ name: "migrate_predictive_back_transition"
namespace: "windowing_frontend"
- description: "A change can use its own layer parameters to animate behind a translucent activity"
- bug: "327332488"
+ description: "Create transition when visibility change from predictive back"
+ bug: "347168362"
+ is_fixed_read_only: true
metadata {
purpose: PURPOSE_BUGFIX
}
diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig
index 4c18bbf..b8c2a5f 100644
--- a/core/java/android/window/flags/windowing_sdk.aconfig
+++ b/core/java/android/window/flags/windowing_sdk.aconfig
@@ -135,14 +135,3 @@
purpose: PURPOSE_BUGFIX
}
}
-
-flag {
- namespace: "windowing_sdk"
- name: "per_user_display_window_settings"
- description: "Whether to store display window settings per user to avoid conflicts"
- bug: "346668297"
- is_fixed_read_only: true
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
diff --git a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
index f9c2947..e8831ec 100644
--- a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
+++ b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
@@ -36,6 +36,7 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.ContentObserver;
@@ -63,6 +64,7 @@
import com.android.internal.R;
import com.android.internal.accessibility.dialog.AccessibilityTarget;
import com.android.internal.accessibility.util.ShortcutUtils;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.function.pooled.PooledLambda;
import java.lang.annotation.Retention;
@@ -122,6 +124,13 @@
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY)
.build();
+
+ /**
+ * An intent action to launch Extra Dim dialog.
+ */
+ @VisibleForTesting
+ static final String ACTION_LAUNCH_REMOVE_EXTRA_DIM_DIALOG =
+ "com.android.systemui.action.LAUNCH_REMOVE_EXTRA_DIM_DIALOG";
private static Map<ComponentName, FrameworkFeatureInfo> sFrameworkShortcutFeaturesMap;
private final Context mContext;
@@ -846,7 +855,7 @@
if (com.android.server.display.feature.flags.Flags.evenDimmer()
&& context.getResources().getBoolean(
com.android.internal.R.bool.config_evenDimmerEnabled)) {
- launchExtraDimDialog();
+ launchExtraDimDialog(context);
return true;
} else {
// Assuming that the default state will be to have the feature off
@@ -863,8 +872,12 @@
}
}
- private void launchExtraDimDialog() {
- // TODO: launch Extra dim dialog for feature migration
+ private void launchExtraDimDialog(Context context) {
+ final Intent intent = new Intent(ACTION_LAUNCH_REMOVE_EXTRA_DIM_DIALOG);
+ intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.setPackage(
+ context.getString(com.android.internal.R.string.config_systemUi));
+ context.sendBroadcastAsUser(intent, UserHandle.SYSTEM);
}
}
diff --git a/core/java/com/android/internal/accessibility/common/ShortcutConstants.java b/core/java/com/android/internal/accessibility/common/ShortcutConstants.java
index a3fcfad..44dceb9 100644
--- a/core/java/com/android/internal/accessibility/common/ShortcutConstants.java
+++ b/core/java/com/android/internal/accessibility/common/ShortcutConstants.java
@@ -72,7 +72,8 @@
UserShortcutType.TRIPLETAP,
UserShortcutType.TWOFINGER_DOUBLETAP,
UserShortcutType.QUICK_SETTINGS,
- UserShortcutType.GESTURE
+ UserShortcutType.GESTURE,
+ UserShortcutType.ALL
})
public @interface UserShortcutType {
int DEFAULT = 0;
@@ -84,6 +85,7 @@
int QUICK_SETTINGS = 1 << 4;
int GESTURE = 1 << 5;
// LINT.ThenChange(:shortcut_type_array)
+ int ALL = SOFTWARE | HARDWARE | TRIPLETAP | TWOFINGER_DOUBLETAP | QUICK_SETTINGS | GESTURE;
}
/**
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 6258f5c..ca4d1b6 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -2960,10 +2960,10 @@
}
private boolean shouldShowStickyContentPreviewNoOrientationCheck() {
- return shouldShowTabs()
- && (mMultiProfilePagerAdapter.getListAdapterForUserHandle(
- UserHandle.of(UserHandle.myUserId())).getCount() > 0
- || shouldShowStickyContentPreviewWhenEmpty())
+ ResolverListAdapter adapter = mMultiProfilePagerAdapter.getListAdapterForUserHandle(
+ UserHandle.of(UserHandle.myUserId()));
+ boolean isEmpty = adapter == null || adapter.getCount() == 0;
+ return shouldShowTabs() && (!isEmpty || shouldShowStickyContentPreviewWhenEmpty())
&& shouldShowContentPreview();
}
diff --git a/core/java/com/android/internal/os/BackgroundThread.java b/core/java/com/android/internal/os/BackgroundThread.java
index b75daed..79996e5 100644
--- a/core/java/com/android/internal/os/BackgroundThread.java
+++ b/core/java/com/android/internal/os/BackgroundThread.java
@@ -16,6 +16,7 @@
package com.android.internal.os;
+import android.annotation.NonNull;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.HandlerThread;
@@ -53,6 +54,7 @@
}
}
+ @NonNull
public static BackgroundThread get() {
synchronized (BackgroundThread.class) {
ensureThreadLocked();
@@ -60,6 +62,7 @@
}
}
+ @NonNull
public static Handler getHandler() {
synchronized (BackgroundThread.class) {
ensureThreadLocked();
@@ -67,6 +70,7 @@
}
}
+ @NonNull
public static Executor getExecutor() {
synchronized (BackgroundThread.class) {
ensureThreadLocked();
diff --git a/core/java/com/android/internal/os/DebugStore.java b/core/java/com/android/internal/os/DebugStore.java
new file mode 100644
index 0000000..4c45fee
--- /dev/null
+++ b/core/java/com/android/internal/os/DebugStore.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.annotation.Nullable;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.Intent;
+import android.content.pm.ServiceInfo;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+
+/**
+ * The DebugStore class provides methods for recording various debug events related to service
+ * lifecycle, broadcast receivers and others.
+ * The DebugStore class facilitates debugging ANR issues by recording time-stamped events
+ * related to service lifecycles, broadcast receivers, and other framework operations. It logs
+ * the start and end times of operations within the ANR timer scope called by framework,
+ * enabling pinpointing of methods and events contributing to ANRs.
+ *
+ * Usage currently includes recording service starts, binds, and asynchronous operations initiated
+ * by broadcast receivers, providing a granular view of system behavior that facilitates
+ * identifying performance bottlenecks and optimizing issue resolution.
+ *
+ * @hide
+ */
+public class DebugStore {
+ private static DebugStoreNative sDebugStoreNative = new DebugStoreNativeImpl();
+
+ @UnsupportedAppUsage
+ @VisibleForTesting
+ public static void setDebugStoreNative(DebugStoreNative nativeImpl) {
+ sDebugStoreNative = nativeImpl;
+ }
+ /**
+ * Records the start of a service.
+ *
+ * @param startId The start ID of the service.
+ * @param flags Additional flags for the service start.
+ * @param intent The Intent associated with the service start.
+ * @return A unique ID for the recorded event.
+ */
+ @UnsupportedAppUsage
+ public static long recordServiceOnStart(int startId, int flags, @Nullable Intent intent) {
+ return sDebugStoreNative.beginEvent(
+ "SvcStart",
+ List.of(
+ "stId",
+ String.valueOf(startId),
+ "flg",
+ Integer.toHexString(flags),
+ "act",
+ Objects.toString(intent != null ? intent.getAction() : null),
+ "comp",
+ Objects.toString(intent != null ? intent.getComponent() : null),
+ "pkg",
+ Objects.toString(intent != null ? intent.getPackage() : null)));
+ }
+
+ /**
+ * Records the creation of a service.
+ *
+ * @param serviceInfo Information about the service being created.
+ * @return A unique ID for the recorded event.
+ */
+ @UnsupportedAppUsage
+ public static long recordServiceCreate(@Nullable ServiceInfo serviceInfo) {
+ return sDebugStoreNative.beginEvent(
+ "SvcCreate",
+ List.of(
+ "name",
+ Objects.toString(serviceInfo != null ? serviceInfo.name : null),
+ "pkg",
+ Objects.toString(serviceInfo != null ? serviceInfo.packageName : null)));
+ }
+
+ /**
+ * Records the binding of a service.
+ *
+ * @param isRebind Indicates whether the service is being rebound.
+ * @param intent The Intent associated with the service binding.
+ * @return A unique identifier for the recorded event.
+ */
+ @UnsupportedAppUsage
+ public static long recordServiceBind(boolean isRebind, @Nullable Intent intent) {
+ return sDebugStoreNative.beginEvent(
+ "SvcBind",
+ List.of(
+ "rebind",
+ String.valueOf(isRebind),
+ "act",
+ Objects.toString(intent != null ? intent.getAction() : null),
+ "cmp",
+ Objects.toString(intent != null ? intent.getComponent() : null),
+ "pkg",
+ Objects.toString(intent != null ? intent.getPackage() : null)));
+ }
+
+ /**
+ * Records an asynchronous operation initiated by a broadcast receiver through calling GoAsync.
+ *
+ * @param receiverClassName The class name of the broadcast receiver.
+ */
+ @UnsupportedAppUsage
+ public static void recordGoAsync(String receiverClassName) {
+ sDebugStoreNative.recordEvent(
+ "GoAsync",
+ List.of(
+ "tname",
+ Thread.currentThread().getName(),
+ "tid",
+ String.valueOf(Thread.currentThread().getId()),
+ "rcv",
+ Objects.toString(receiverClassName)));
+ }
+
+ /**
+ * Records the completion of a broadcast operation through calling Finish.
+ *
+ * @param receiverClassName The class of the broadcast receiver that completed the operation.
+ */
+ @UnsupportedAppUsage
+ public static void recordFinish(String receiverClassName) {
+ sDebugStoreNative.recordEvent(
+ "Finish",
+ List.of(
+ "tname",
+ Thread.currentThread().getName(),
+ "tid",
+ String.valueOf(Thread.currentThread().getId()),
+ "rcv",
+ Objects.toString(receiverClassName)));
+ }
+ /**
+ * Records the completion of a long-running looper message.
+ *
+ * @param messageCode The code representing the type of the message.
+ * @param targetClass The FQN of the class that handled the message.
+ * @param elapsedTimeMs The time that was taken to process the message, in milliseconds.
+ */
+ @UnsupportedAppUsage
+ public static void recordLongLooperMessage(int messageCode, String targetClass,
+ long elapsedTimeMs) {
+ sDebugStoreNative.recordEvent(
+ "LooperMsg",
+ List.of(
+ "code",
+ String.valueOf(messageCode),
+ "trgt",
+ Objects.toString(targetClass),
+ "elapsed",
+ String.valueOf(elapsedTimeMs)));
+ }
+
+
+ /**
+ * Records the reception of a broadcast.
+ *
+ * @param intent The Intent associated with the broadcast.
+ * @return A unique ID for the recorded event.
+ */
+ @UnsupportedAppUsage
+ public static long recordBroadcastHandleReceiver(@Nullable Intent intent) {
+ return sDebugStoreNative.beginEvent(
+ "HandleReceiver",
+ List.of(
+ "tname", Thread.currentThread().getName(),
+ "tid", String.valueOf(Thread.currentThread().getId()),
+ "act", Objects.toString(intent != null ? intent.getAction() : null),
+ "cmp", Objects.toString(intent != null ? intent.getComponent() : null),
+ "pkg", Objects.toString(intent != null ? intent.getPackage() : null)));
+ }
+
+ /**
+ * Ends a previously recorded event.
+ *
+ * @param id The unique ID of the event to be ended.
+ */
+ @UnsupportedAppUsage
+ public static void recordEventEnd(long id) {
+ sDebugStoreNative.endEvent(id, Collections.emptyList());
+ }
+
+ /**
+ * An interface for a class that acts as a wrapper for the static native methods
+ * of the Debug Store.
+ *
+ * It allows us to mock static native methods in our tests and should be removed
+ * once mocking static methods becomes easier.
+ */
+ @VisibleForTesting
+ public interface DebugStoreNative {
+ /**
+ * Begins an event with the given name and attributes.
+ */
+ long beginEvent(String eventName, List<String> attributes);
+ /**
+ * Ends an event with the given ID and attributes.
+ */
+ void endEvent(long id, List<String> attributes);
+ /**
+ * Records an event with the given name and attributes.
+ */
+ void recordEvent(String eventName, List<String> attributes);
+ }
+
+ private static class DebugStoreNativeImpl implements DebugStoreNative {
+ @Override
+ public long beginEvent(String eventName, List<String> attributes) {
+ return DebugStore.beginEventNative(eventName, attributes);
+ }
+
+ @Override
+ public void endEvent(long id, List<String> attributes) {
+ DebugStore.endEventNative(id, attributes);
+ }
+
+ @Override
+ public void recordEvent(String eventName, List<String> attributes) {
+ DebugStore.recordEventNative(eventName, attributes);
+ }
+ }
+
+ private static native long beginEventNative(String eventName, List<String> attributes);
+
+ private static native void endEventNative(long id, List<String> attributes);
+
+ private static native void recordEventNative(String eventName, List<String> attributes);
+}
diff --git a/core/java/com/android/internal/os/flags.aconfig b/core/java/com/android/internal/os/flags.aconfig
index 2ad6651..c7117e9 100644
--- a/core/java/com/android/internal/os/flags.aconfig
+++ b/core/java/com/android/internal/os/flags.aconfig
@@ -19,4 +19,12 @@
metadata {
purpose: PURPOSE_BUGFIX
}
+}
+
+flag {
+ name: "debug_store_enabled"
+ namespace: "stability"
+ description: "If the debug store is enabled."
+ bug: "314735374"
+ is_fixed_read_only: true
}
\ No newline at end of file
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index e29f256..1d43f6f 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -51,8 +51,7 @@
void showWirelessChargingAnimation(int batteryLevel);
- void setImeWindowStatus(int displayId, in IBinder token, int vis, int backDisposition,
- boolean showImeSwitcher);
+ void setImeWindowStatus(int displayId, int vis, int backDisposition, boolean showImeSwitcher);
void setWindowState(int display, int window, int state);
void showRecentApps(boolean triggeredFromAltTab);
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index fc60f06..ff08dd2 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -61,8 +61,7 @@
void setIconVisibility(String slot, boolean visible);
@UnsupportedAppUsage
void removeIcon(String slot);
- void setImeWindowStatus(int displayId, in IBinder token, int vis, int backDisposition,
- boolean showImeSwitcher);
+ void setImeWindowStatus(int displayId, int vis, int backDisposition, boolean showImeSwitcher);
void expandSettingsPanel(String subPanel);
// ---- Methods below are for use by the status bar policy services ----
diff --git a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
index 4f827cd..7240aff 100644
--- a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
+++ b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
@@ -16,7 +16,6 @@
package com.android.internal.statusbar;
-import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArrayMap;
@@ -35,7 +34,6 @@
public final int mImeBackDisposition; // switch[4]
public final boolean mShowImeSwitcher; // switch[5]
public final int mDisabledFlags2; // switch[6]
- public final IBinder mImeToken;
public final boolean mNavbarColorManagedByIme;
public final int mBehavior;
public final int mRequestedVisibleTypes;
@@ -45,7 +43,7 @@
public RegisterStatusBarResult(ArrayMap<String, StatusBarIcon> icons, int disabledFlags1,
int appearance, AppearanceRegion[] appearanceRegions, int imeWindowVis,
- int imeBackDisposition, boolean showImeSwitcher, int disabledFlags2, IBinder imeToken,
+ int imeBackDisposition, boolean showImeSwitcher, int disabledFlags2,
boolean navbarColorManagedByIme, int behavior, int requestedVisibleTypes,
String packageName, int transientBarTypes, LetterboxDetails[] letterboxDetails) {
mIcons = new ArrayMap<>(icons);
@@ -56,7 +54,6 @@
mImeBackDisposition = imeBackDisposition;
mShowImeSwitcher = showImeSwitcher;
mDisabledFlags2 = disabledFlags2;
- mImeToken = imeToken;
mNavbarColorManagedByIme = navbarColorManagedByIme;
mBehavior = behavior;
mRequestedVisibleTypes = requestedVisibleTypes;
@@ -80,7 +77,6 @@
dest.writeInt(mImeBackDisposition);
dest.writeBoolean(mShowImeSwitcher);
dest.writeInt(mDisabledFlags2);
- dest.writeStrongBinder(mImeToken);
dest.writeBoolean(mNavbarColorManagedByIme);
dest.writeInt(mBehavior);
dest.writeInt(mRequestedVisibleTypes);
@@ -106,7 +102,6 @@
final int imeBackDisposition = source.readInt();
final boolean showImeSwitcher = source.readBoolean();
final int disabledFlags2 = source.readInt();
- final IBinder imeToken = source.readStrongBinder();
final boolean navbarColorManagedByIme = source.readBoolean();
final int behavior = source.readInt();
final int requestedVisibleTypes = source.readInt();
@@ -116,7 +111,7 @@
source.readParcelableArray(null, LetterboxDetails.class);
return new RegisterStatusBarResult(icons, disabledFlags1, appearance,
appearanceRegions, imeWindowVis, imeBackDisposition, showImeSwitcher,
- disabledFlags2, imeToken, navbarColorManagedByIme, behavior,
+ disabledFlags2, navbarColorManagedByIme, behavior,
requestedVisibleTypes, packageName, transientBarTypes,
letterboxDetails);
}
diff --git a/core/java/com/android/internal/util/ContrastColorUtil.java b/core/java/com/android/internal/util/ContrastColorUtil.java
index 77de272..0fd1391 100644
--- a/core/java/com/android/internal/util/ContrastColorUtil.java
+++ b/core/java/com/android/internal/util/ContrastColorUtil.java
@@ -31,6 +31,7 @@
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.graphics.drawable.VectorDrawable;
+import android.text.NoCopySpan;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.BackgroundColorSpan;
@@ -188,6 +189,10 @@
Object[] spans = ss.getSpans(0, ss.length(), Object.class);
SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString());
for (Object span : spans) {
+ if (span instanceof NoCopySpan) {
+ // These spans can contain external references and should not be copied.
+ continue;
+ }
Object resultSpan = span;
if (resultSpan instanceof CharacterStyle) {
resultSpan = ((CharacterStyle) span).getUnderlying();
@@ -254,6 +259,10 @@
Object[] spans = ss.getSpans(0, ss.length(), Object.class);
SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString());
for (Object span : spans) {
+ if (span instanceof NoCopySpan) {
+ // These spans can contain external references and should not be copied.
+ continue;
+ }
Object resultSpan = span;
if (resultSpan instanceof CharacterStyle) {
resultSpan = ((CharacterStyle) span).getUnderlying();
@@ -300,6 +309,10 @@
Object[] spans = ss.getSpans(0, ss.length(), Object.class);
SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString());
for (Object span : spans) {
+ if (span instanceof NoCopySpan) {
+ // These spans can contain external references and should not be copied.
+ continue;
+ }
Object resultSpan = span;
int spanStart = ss.getSpanStart(span);
int spanEnd = ss.getSpanEnd(span);
diff --git a/core/java/com/android/internal/widget/OWNERS b/core/java/com/android/internal/widget/OWNERS
index cf2f202..2d1c2f0 100644
--- a/core/java/com/android/internal/widget/OWNERS
+++ b/core/java/com/android/internal/widget/OWNERS
@@ -3,7 +3,9 @@
per-file ViewPager.java = mount@google.com
# LockSettings related
-per-file *LockPattern* = file:/services/core/java/com/android/server/locksettings/OWNERS
+per-file LockPatternChecker.java = file:/services/core/java/com/android/server/locksettings/OWNERS
+per-file LockPatternUtils.java = file:/services/core/java/com/android/server/locksettings/OWNERS
+per-file LockPatternView.java = file:/packages/SystemUI/OWNERS
per-file *LockScreen* = file:/services/core/java/com/android/server/locksettings/OWNERS
per-file *Lockscreen* = file:/services/core/java/com/android/server/locksettings/OWNERS
per-file *LockSettings* = file:/services/core/java/com/android/server/locksettings/OWNERS
diff --git a/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java b/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java
index 5c2a167..effbbe2 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java
@@ -18,6 +18,11 @@
import com.android.internal.widget.remotecompose.core.operations.NamedVariable;
import com.android.internal.widget.remotecompose.core.operations.RootContentBehavior;
import com.android.internal.widget.remotecompose.core.operations.Theme;
+import com.android.internal.widget.remotecompose.core.operations.layout.Component;
+import com.android.internal.widget.remotecompose.core.operations.layout.ComponentEnd;
+import com.android.internal.widget.remotecompose.core.operations.layout.ComponentStartOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.LayoutComponent;
+import com.android.internal.widget.remotecompose.core.operations.layout.RootLayoutComponent;
import java.util.ArrayList;
import java.util.HashSet;
@@ -30,6 +35,9 @@
public class CoreDocument {
ArrayList<Operation> mOperations;
+
+ RootLayoutComponent mRootLayoutComponent = null;
+
RemoteComposeState mRemoteComposeState = new RemoteComposeState();
TimeVariables mTimeVariables = new TimeVariables();
// Semantic version of the document
@@ -81,7 +89,6 @@
public void setHeight(int height) {
this.mHeight = height;
mRemoteComposeState.setWindowHeight(height);
-
}
public RemoteComposeBuffer getBuffer() {
@@ -259,10 +266,43 @@
translateOutput[1] = translateY;
}
+ /**
+ * Returns the list of click areas
+ * @return list of click areas in document coordinates
+ */
public Set<ClickAreaRepresentation> getClickAreas() {
return mClickAreas;
}
+ /**
+ * Returns the root layout component
+ * @return returns the root component if it exists, null otherwise
+ */
+ public RootLayoutComponent getRootLayoutComponent() {
+ return mRootLayoutComponent;
+ }
+
+ /**
+ * Invalidate the document for layout measures. This will trigger a layout remeasure pass.
+ */
+ public void invalidateMeasure() {
+ if (mRootLayoutComponent != null) {
+ mRootLayoutComponent.invalidateMeasure();
+ }
+ }
+
+ /**
+ * Returns the component with the given id
+ * @param id component id
+ * @return the component if it exists, null otherwise
+ */
+ public Component getComponent(int id) {
+ if (mRootLayoutComponent != null) {
+ return mRootLayoutComponent.getComponent(id);
+ }
+ return null;
+ }
+
public interface ClickCallbacks {
void click(int id, String metadata);
}
@@ -354,7 +394,54 @@
public void initFromBuffer(RemoteComposeBuffer buffer) {
mOperations = new ArrayList<Operation>();
buffer.inflateFromBuffer(mOperations);
+ mOperations = inflateComponents(mOperations);
mBuffer = buffer;
+ for (Operation op : mOperations) {
+ if (op instanceof RootLayoutComponent) {
+ mRootLayoutComponent = (RootLayoutComponent) op;
+ break;
+ }
+ }
+ if (mRootLayoutComponent != null) {
+ mRootLayoutComponent.assignIds();
+ }
+ }
+
+ /**
+ * Inflate a component tree
+ * @param operations flat list of operations
+ * @return nested list of operations / components
+ */
+ private ArrayList<Operation> inflateComponents(ArrayList<Operation> operations) {
+ Component currentComponent = null;
+ ArrayList<Component> components = new ArrayList<>();
+ ArrayList<Operation> finalOperationsList = new ArrayList<>();
+ ArrayList<Operation> ops = finalOperationsList;
+
+ for (Operation o : operations) {
+ if (o instanceof ComponentStartOperation) {
+ Component component = (Component) o;
+ component.setParent(currentComponent);
+ components.add(component);
+ currentComponent = component;
+ ops.add(currentComponent);
+ ops = currentComponent.getList();
+ } else if (o instanceof ComponentEnd) {
+ if (currentComponent instanceof LayoutComponent) {
+ ((LayoutComponent) currentComponent).inflate();
+ }
+ components.remove(components.size() - 1);
+ if (!components.isEmpty()) {
+ currentComponent = components.get(components.size() - 1);
+ ops = currentComponent.getList();
+ } else {
+ ops = finalOperationsList;
+ }
+ } else {
+ ops.add(o);
+ }
+ }
+ return ops;
}
/**
@@ -559,6 +646,18 @@
context.loadFloat(RemoteContext.ID_WINDOW_WIDTH, getWidth());
context.loadFloat(RemoteContext.ID_WINDOW_HEIGHT, getHeight());
mRepaintNext = context.updateOps();
+ if (mRootLayoutComponent != null) {
+ if (context.mWidth != mRootLayoutComponent.getWidth()
+ || context.mHeight != mRootLayoutComponent.getHeight()) {
+ mRootLayoutComponent.invalidateMeasure();
+ }
+ if (mRootLayoutComponent.needsMeasure()) {
+ mRootLayoutComponent.layout(context);
+ }
+ if (mRootLayoutComponent.doesNeedsRepaint()) {
+ mRepaintNext = 1;
+ }
+ }
for (Operation op : mOperations) {
// operations will only be executed if no theme is set (ie UNSPECIFIED)
// or the theme is equal as the one passed in argument to paint.
diff --git a/core/java/com/android/internal/widget/remotecompose/core/Operation.java b/core/java/com/android/internal/widget/remotecompose/core/Operation.java
index 7cb9a42..4a8b3d7 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/Operation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/Operation.java
@@ -37,4 +37,3 @@
*/
String deepToString(String indent);
}
-
diff --git a/core/java/com/android/internal/widget/remotecompose/core/Operations.java b/core/java/com/android/internal/widget/remotecompose/core/Operations.java
index 4b8dbf6..9cb024b 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/Operations.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/Operations.java
@@ -54,6 +54,21 @@
import com.android.internal.widget.remotecompose.core.operations.TextFromFloat;
import com.android.internal.widget.remotecompose.core.operations.TextMerge;
import com.android.internal.widget.remotecompose.core.operations.Theme;
+import com.android.internal.widget.remotecompose.core.operations.layout.ComponentEnd;
+import com.android.internal.widget.remotecompose.core.operations.layout.ComponentStart;
+import com.android.internal.widget.remotecompose.core.operations.layout.LayoutComponentContent;
+import com.android.internal.widget.remotecompose.core.operations.layout.RootLayoutComponent;
+import com.android.internal.widget.remotecompose.core.operations.layout.animation.AnimationSpec;
+import com.android.internal.widget.remotecompose.core.operations.layout.managers.BoxLayout;
+import com.android.internal.widget.remotecompose.core.operations.layout.managers.ColumnLayout;
+import com.android.internal.widget.remotecompose.core.operations.layout.managers.RowLayout;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.BackgroundModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.BorderModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ClipRectModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.HeightModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.PaddingModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.RoundedClipRectModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.WidthModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.utilities.IntMap;
import com.android.internal.widget.remotecompose.core.types.BooleanConstant;
import com.android.internal.widget.remotecompose.core.types.IntegerConstant;
@@ -117,6 +132,27 @@
public static final int INTEGER_EXPRESSION = 144;
/////////////////////////////////////////======================
+
+ ////////////////////////////////////////
+ // Layout commands
+ ////////////////////////////////////////
+
+ public static final int LAYOUT_ROOT = 200;
+ public static final int LAYOUT_CONTENT = 201;
+ public static final int LAYOUT_BOX = 202;
+ public static final int LAYOUT_ROW = 203;
+ public static final int LAYOUT_COLUMN = 204;
+ public static final int COMPONENT_START = 2;
+ public static final int COMPONENT_END = 3;
+ public static final int MODIFIER_WIDTH = 16;
+ public static final int MODIFIER_HEIGHT = 67;
+ public static final int MODIFIER_BACKGROUND = 55;
+ public static final int MODIFIER_BORDER = 107;
+ public static final int MODIFIER_PADDING = 58;
+ public static final int MODIFIER_CLIP_RECT = 108;
+ public static final int MODIFIER_ROUNDED_CLIP_RECT = 54;
+ public static final int ANIMATION_SPEC = 14;
+
public static IntMap<CompanionOperation> map = new IntMap<>();
static {
@@ -162,6 +198,26 @@
map.put(DATA_INT, IntegerConstant.COMPANION);
map.put(INTEGER_EXPRESSION, IntegerExpression.COMPANION);
map.put(DATA_BOOLEAN, BooleanConstant.COMPANION);
+
+ // Layout
+
+ map.put(COMPONENT_START, ComponentStart.COMPANION);
+ map.put(COMPONENT_END, ComponentEnd.COMPANION);
+ map.put(ANIMATION_SPEC, AnimationSpec.COMPANION);
+
+ map.put(MODIFIER_WIDTH, WidthModifierOperation.COMPANION);
+ map.put(MODIFIER_HEIGHT, HeightModifierOperation.COMPANION);
+ map.put(MODIFIER_PADDING, PaddingModifierOperation.COMPANION);
+ map.put(MODIFIER_BACKGROUND, BackgroundModifierOperation.COMPANION);
+ map.put(MODIFIER_BORDER, BorderModifierOperation.COMPANION);
+ map.put(MODIFIER_ROUNDED_CLIP_RECT, RoundedClipRectModifierOperation.COMPANION);
+ map.put(MODIFIER_CLIP_RECT, ClipRectModifierOperation.COMPANION);
+
+ map.put(LAYOUT_ROOT, RootLayoutComponent.COMPANION);
+ map.put(LAYOUT_CONTENT, LayoutComponentContent.COMPANION);
+ map.put(LAYOUT_BOX, BoxLayout.COMPANION);
+ map.put(LAYOUT_COLUMN, ColumnLayout.COMPANION);
+ map.put(LAYOUT_ROW, RowLayout.COMPANION);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java b/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java
index 6d8a442..665fcb7 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java
@@ -23,6 +23,10 @@
public abstract class PaintContext {
protected RemoteContext mContext;
+ public RemoteContext getContext() {
+ return mContext;
+ }
+
public PaintContext(RemoteContext context) {
this.mContext = context;
}
@@ -31,6 +35,28 @@
this.mContext = context;
}
+ /**
+ * convenience function to call matrixSave()
+ */
+ public void save() {
+ matrixSave();
+ }
+
+ /**
+ * convenience function to call matrixRestore()
+ */
+ public void restore() {
+ matrixRestore();
+ }
+
+ /**
+ * convenience function to call matrixSave()
+ */
+ public void saveLayer(float x, float y, float width, float height) {
+ // TODO
+ matrixSave();
+ }
+
public abstract void drawBitmap(int imageId,
int srcLeft, int srcTop, int srcRight, int srcBottom,
int dstLeft, int dstTop, int dstRight, int dstBottom,
@@ -197,8 +223,49 @@
public abstract void clipPath(int pathId, int regionOp);
/**
+ * Clip based ona round rect
+ * @param width
+ * @param height
+ * @param topStart
+ * @param topEnd
+ * @param bottomStart
+ * @param bottomEnd
+ */
+ public abstract void roundedClipRect(float width, float height,
+ float topStart, float topEnd,
+ float bottomStart, float bottomEnd);
+
+ /**
* Reset the paint
*/
public abstract void reset();
+
+ /**
+ * Returns true if the context is in debug mode
+ *
+ * @return true if in debug mode, false otherwise
+ */
+ public boolean isDebug() {
+ return mContext.isDebug();
+ }
+
+ /**
+ * Returns true if layout animations are enabled
+ *
+ * @return true if animations are enabled, false otherwise
+ */
+ public boolean isAnimationEnabled() {
+ return mContext.isAnimationEnabled();
+ }
+
+ /**
+ * Utility function to log comments
+ *
+ * @param content the content to log
+ */
+ public void log(String content) {
+ System.out.println("[LOG] " + content);
+ }
+
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/PaintOperation.java b/core/java/com/android/internal/widget/remotecompose/core/PaintOperation.java
index 2f3fe57..4a1ccc9 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/PaintOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/PaintOperation.java
@@ -23,9 +23,11 @@
@Override
public void apply(RemoteContext context) {
- if (context.getMode() == RemoteContext.ContextMode.PAINT
- && context.getPaintContext() != null) {
- paint((PaintContext) context.getPaintContext());
+ if (context.getMode() == RemoteContext.ContextMode.PAINT) {
+ PaintContext paintContext = context.getPaintContext();
+ if (paintContext != null) {
+ paint(paintContext);
+ }
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java
index f5f155e..333951b 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java
@@ -54,6 +54,18 @@
import com.android.internal.widget.remotecompose.core.operations.TextMerge;
import com.android.internal.widget.remotecompose.core.operations.Theme;
import com.android.internal.widget.remotecompose.core.operations.Utils;
+import com.android.internal.widget.remotecompose.core.operations.layout.ComponentEnd;
+import com.android.internal.widget.remotecompose.core.operations.layout.ComponentStart;
+import com.android.internal.widget.remotecompose.core.operations.layout.LayoutComponentContent;
+import com.android.internal.widget.remotecompose.core.operations.layout.RootLayoutComponent;
+import com.android.internal.widget.remotecompose.core.operations.layout.managers.BoxLayout;
+import com.android.internal.widget.remotecompose.core.operations.layout.managers.ColumnLayout;
+import com.android.internal.widget.remotecompose.core.operations.layout.managers.RowLayout;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.BackgroundModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.BorderModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ClipRectModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.PaddingModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.RoundedClipRectModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.paint.PaintBundle;
import com.android.internal.widget.remotecompose.core.operations.utilities.easing.FloatAnimation;
import com.android.internal.widget.remotecompose.core.types.IntegerConstant;
@@ -132,8 +144,9 @@
* @param contentDescription content description of the document
* @param capabilities bitmask indicating needed capabilities (unused for now)
*/
- public void header(int width, int height, String contentDescription, long capabilities) {
- Header.COMPANION.apply(mBuffer, width, height, capabilities);
+ public void header(int width, int height, String contentDescription,
+ float density, long capabilities) {
+ Header.COMPANION.apply(mBuffer, width, height, density, capabilities);
int contentDescriptionId = 0;
if (contentDescription != null) {
contentDescriptionId = addText(contentDescription);
@@ -149,7 +162,7 @@
* @param contentDescription content description of the document
*/
public void header(int width, int height, String contentDescription) {
- header(width, height, contentDescription, 0);
+ header(width, height, contentDescription, 1f, 0);
}
/**
@@ -857,7 +870,7 @@
}
/**
- * Sets the clip based on clip rec
+ * Sets the clip based on clip rect
* @param left
* @param top
* @param right
@@ -1074,5 +1087,128 @@
NamedVariable.COLOR_TYPE, name);
}
+ /**
+ * Add a component start tag
+ * @param type type of component
+ * @param id component id
+ */
+ public void addComponentStart(int type, int id) {
+ switch (type) {
+ case ComponentStart.ROOT_LAYOUT: {
+ RootLayoutComponent.COMPANION.apply(mBuffer);
+ } break;
+ case ComponentStart.LAYOUT_CONTENT: {
+ LayoutComponentContent.COMPANION.apply(mBuffer);
+ } break;
+ case ComponentStart.LAYOUT_BOX: {
+ BoxLayout.COMPANION.apply(mBuffer, id, -1,
+ BoxLayout.CENTER, BoxLayout.CENTER);
+ } break;
+ case ComponentStart.LAYOUT_ROW: {
+ RowLayout.COMPANION.apply(mBuffer, id, -1,
+ RowLayout.START, RowLayout.TOP, 0f);
+ } break;
+ case ComponentStart.LAYOUT_COLUMN: {
+ ColumnLayout.COMPANION.apply(mBuffer, id, -1,
+ ColumnLayout.START, ColumnLayout.TOP, 0f);
+ } break;
+ default:
+ ComponentStart.Companion.apply(mBuffer,
+ type, id, 0f, 0f);
+ }
+ }
+
+ /**
+ * Add a component start tag
+ * @param type type of component
+ */
+ public void addComponentStart(int type) {
+ addComponentStart(type, -1);
+ }
+
+ /**
+ * Add a component end tag
+ */
+ public void addComponentEnd() {
+ ComponentEnd.Companion.apply(mBuffer);
+ }
+
+ /**
+ * Add a background modifier of provided color
+ * @param color the color of the background
+ * @param shape the background shape -- SHAPE_RECTANGLE, SHAPE_CIRCLE
+ */
+ public void addModifierBackground(int color, int shape) {
+ float r = ((color >> 16) & 0xff) / 255.0f;
+ float g = ((color >> 8) & 0xff) / 255.0f;
+ float b = ((color) & 0xff) / 255.0f;
+ float a = ((color >> 24) & 0xff) / 255.0f;
+ BackgroundModifierOperation.COMPANION.apply(mBuffer, 0f, 0f, 0f, 0f,
+ r, g, b, a, shape);
+ }
+
+ /**
+ * Add a border modifier
+ * @param borderWidth the border width
+ * @param borderRoundedCorner the rounded corner radius if the shape is ROUNDED_RECT
+ * @param color the color of the border
+ * @param shape the shape of the border
+ */
+ public void addModifierBorder(float borderWidth, float borderRoundedCorner,
+ int color, int shape) {
+ float r = ((color >> 16) & 0xff) / 255.0f;
+ float g = ((color >> 8) & 0xff) / 255.0f;
+ float b = ((color) & 0xff) / 255.0f;
+ float a = ((color >> 24) & 0xff) / 255.0f;
+ BorderModifierOperation.COMPANION.apply(mBuffer, 0f, 0f, 0f, 0f,
+ borderWidth, borderRoundedCorner, r, g, b, a, shape);
+ }
+
+ /**
+ * Add a padding modifier
+ * @param left left padding
+ * @param top top padding
+ * @param right right padding
+ * @param bottom bottom padding
+ */
+ public void addModifierPadding(float left, float top, float right, float bottom) {
+ PaddingModifierOperation.COMPANION.apply(mBuffer, left, top, right, bottom);
+ }
+
+
+ /**
+ * Sets the clip based on rounded clip rect
+ * @param topStart
+ * @param topEnd
+ * @param bottomStart
+ * @param bottomEnd
+ */
+ public void addRoundClipRectModifier(float topStart, float topEnd,
+ float bottomStart, float bottomEnd) {
+ RoundedClipRectModifierOperation.COMPANION.apply(mBuffer,
+ topStart, topEnd, bottomStart, bottomEnd);
+ }
+
+ public void addClipRectModifier() {
+ ClipRectModifierOperation.COMPANION.apply(mBuffer);
+ }
+
+ public void addBoxStart(int componentId, int animationId,
+ int horizontal, int vertical) {
+ BoxLayout.COMPANION.apply(mBuffer, componentId, animationId,
+ horizontal, vertical);
+ }
+
+ public void addRowStart(int componentId, int animationId,
+ int horizontal, int vertical, float spacedBy) {
+ RowLayout.COMPANION.apply(mBuffer, componentId, animationId,
+ horizontal, vertical, spacedBy);
+ }
+
+ public void addColumnStart(int componentId, int animationId,
+ int horizontal, int vertical, float spacedBy) {
+ ColumnLayout.COMPANION.apply(mBuffer, componentId, animationId,
+ horizontal, vertical, spacedBy);
+ }
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java
index 41eeb5b..893dcce 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java
@@ -19,6 +19,7 @@
import com.android.internal.widget.remotecompose.core.operations.ShaderData;
import com.android.internal.widget.remotecompose.core.operations.Theme;
import com.android.internal.widget.remotecompose.core.operations.Utils;
+import com.android.internal.widget.remotecompose.core.operations.layout.Component;
/**
* Specify an abstract context used to playback RemoteCompose documents
@@ -35,12 +36,26 @@
ContextMode mMode = ContextMode.UNSET;
boolean mDebug = false;
+
private int mTheme = Theme.UNSPECIFIED;
public float mWidth = 0f;
public float mHeight = 0f;
private float mAnimationTime;
+ private boolean mAnimate = true;
+
+ public Component lastComponent;
+ public long currentTime = 0L;
+
+ public boolean isAnimationEnabled() {
+ return mAnimate;
+ }
+
+ public void setAnimationEnabled(boolean value) {
+ mAnimate = value;
+ }
+
/**
* Load a path under an id.
* Paths can be use in clip drawPath and drawTweenPath
@@ -333,9 +348,11 @@
public static final float FLOAT_COMPONENT_HEIGHT = Utils.asNan(ID_COMPONENT_HEIGHT);
// ID_OFFSET_TO_UTC is the offset from UTC in sec (typically / 3600f)
public static final float FLOAT_OFFSET_TO_UTC = Utils.asNan(ID_OFFSET_TO_UTC);
+
///////////////////////////////////////////////////////////////////////////////////////////////
// Click handling
///////////////////////////////////////////////////////////////////////////////////////////////
+
public abstract void addClickArea(
int id,
int contentDescription,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt b/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentationBuilder.java
similarity index 68%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
copy to core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentationBuilder.java
index 1f04a44..ccbcdf6 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
+++ b/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentationBuilder.java
@@ -13,13 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.internal.widget.remotecompose.core.documentation;
-package com.android.systemui.activatable
-
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.TestScope
-
-/** Activates [activatable] for the duration of the test. */
-fun Activatable.activateIn(testScope: TestScope) {
- testScope.backgroundScope.launch { activate() }
+public interface DocumentationBuilder {
+ void add(String value);
+ Operation operation(String category, int id, String name);
+ Operation wipOperation(String category, int id, String name);
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt b/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentedCompanionOperation.java
similarity index 68%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
copy to core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentedCompanionOperation.java
index 1f04a44..6a98b78 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
+++ b/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentedCompanionOperation.java
@@ -13,13 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.internal.widget.remotecompose.core.documentation;
-package com.android.systemui.activatable
+import com.android.internal.widget.remotecompose.core.CompanionOperation;
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.TestScope
-
-/** Activates [activatable] for the duration of the test. */
-fun Activatable.activateIn(testScope: TestScope) {
- testScope.backgroundScope.launch { activate() }
+public interface DocumentedCompanionOperation extends CompanionOperation {
+ void documentation(DocumentationBuilder doc);
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/documentation/Operation.java b/core/java/com/android/internal/widget/remotecompose/core/documentation/Operation.java
new file mode 100644
index 0000000..643b925
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/documentation/Operation.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.documentation;
+
+import java.util.ArrayList;
+
+public class Operation {
+ public static final int LAYOUT = 0;
+ public static final int INT = 0;
+ public static final int FLOAT = 1;
+ public static final int BOOLEAN = 2;
+ public static final int BUFFER = 4;
+ public static final int UTF8 = 5;
+ public static final int BYTE = 6;
+ public static final int VALUE = 7;
+ public static final int LONG = 8;
+
+ String mCategory;
+ int mId;
+ String mName;
+ String mDescription;
+
+ boolean mWIP;
+ String mTextExamples;
+
+ ArrayList<StringPair> mExamples = new ArrayList<>();
+ ArrayList<OperationField> mFields = new ArrayList<>();
+
+ int mExamplesWidth = 100;
+ int mExamplesHeight = 100;
+
+
+ public static String getType(int type) {
+ switch (type) {
+ case (INT): return "INT";
+ case (FLOAT): return "FLOAT";
+ case (BOOLEAN): return "BOOLEAN";
+ case (BUFFER): return "BUFFER";
+ case (UTF8): return "UTF8";
+ case (BYTE): return "BYTE";
+ case (VALUE): return "VALUE";
+ case (LONG): return "LONG";
+ }
+ return "UNKNOWN";
+ }
+
+ public Operation(String category, int id, String name, boolean wip) {
+ mCategory = category;
+ mId = id;
+ mName = name;
+ mWIP = wip;
+ }
+
+ public Operation(String category, int id, String name) {
+ this(category, id, name, false);
+ }
+
+ public ArrayList<OperationField> getFields() {
+ return mFields;
+ }
+
+ public String getCategory() {
+ return mCategory;
+ }
+
+ public int getId() {
+ return mId;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public boolean isWIP() {
+ return mWIP;
+ }
+
+ public int getSizeFields() {
+ int size = 0;
+ for (OperationField field : mFields) {
+ size += field.getSize();
+ }
+ return size;
+ }
+
+ public String getDescription() {
+ return mDescription;
+ }
+
+ public String getTextExamples() {
+ return mTextExamples;
+ }
+
+ public ArrayList<StringPair> getExamples() {
+ return mExamples;
+ }
+
+ public int getExamplesWidth() {
+ return mExamplesWidth;
+ }
+
+ public int getExamplesHeight() {
+ return mExamplesHeight;
+ }
+
+ public Operation field(int type, String name, String description) {
+ mFields.add(new OperationField(type, name, description));
+ return this;
+ }
+
+ public Operation possibleValues(String name, int value) {
+ if (!mFields.isEmpty()) {
+ mFields.get(mFields.size() - 1).possibleValue(name, "" + value);
+ }
+ return this;
+ }
+
+ public Operation description(String description) {
+ mDescription = description;
+ return this;
+ }
+
+ public Operation examples(String examples) {
+ mTextExamples = examples;
+ return this;
+ }
+
+ public Operation exampleImage(String name, String imagePath) {
+ mExamples.add(new StringPair(name, imagePath));
+ return this;
+ }
+
+ public Operation examplesDimension(int width, int height) {
+ mExamplesWidth = width;
+ mExamplesHeight = height;
+ return this;
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/documentation/OperationField.java b/core/java/com/android/internal/widget/remotecompose/core/documentation/OperationField.java
new file mode 100644
index 0000000..fc73f4ed6
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/documentation/OperationField.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.documentation;
+
+import java.util.ArrayList;
+
+public class OperationField {
+ int mType;
+ String mName;
+ String mDescription;
+ ArrayList<StringPair> mPossibleValues = new ArrayList<>();
+
+ public OperationField(int type, String name, String description) {
+ mType = type;
+ mName = name;
+ mDescription = description;
+ }
+ public int getType() {
+ return mType;
+ }
+ public String getName() {
+ return mName;
+ }
+ public String getDescription() {
+ return mDescription;
+ }
+ public ArrayList<StringPair> getPossibleValues() {
+ return mPossibleValues;
+ }
+ public void possibleValue(String name, String value) {
+ mPossibleValues.add(new StringPair(name, value));
+ }
+ public boolean hasEnumeratedValues() {
+ return !mPossibleValues.isEmpty();
+ }
+ public int getSize() {
+ switch (mType) {
+ case (Operation.BYTE) : return 1;
+ case (Operation.INT) : return 4;
+ case (Operation.FLOAT) : return 4;
+ case (Operation.LONG) : return 8;
+ default : return 0;
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt b/core/java/com/android/internal/widget/remotecompose/core/documentation/StringPair.java
similarity index 63%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
copy to core/java/com/android/internal/widget/remotecompose/core/documentation/StringPair.java
index 1f04a44..787bb54 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
+++ b/core/java/com/android/internal/widget/remotecompose/core/documentation/StringPair.java
@@ -13,13 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.internal.widget.remotecompose.core.documentation;
+public class StringPair {
+ String mName;
+ String mValue;
-package com.android.systemui.activatable
+ StringPair(String name, String value) {
+ mName = name;
+ mValue = value;
+ }
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.TestScope
-
-/** Activates [activatable] for the duration of the test. */
-fun Activatable.activateIn(testScope: TestScope) {
- testScope.backgroundScope.launch { activate() }
+ public String getName() {
+ return mName;
+ }
+ public String getValue() {
+ return mValue;
+ }
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase4.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase4.java
index ec35a16..53a3aa9 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase4.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase4.java
@@ -41,10 +41,10 @@
}
};
protected String mName = "DrawRectBase";
- float mX1;
- float mY1;
- float mX2;
- float mY2;
+ protected float mX1;
+ protected float mY1;
+ protected float mX2;
+ protected float mY2;
float mX1Value;
float mY1Value;
float mX2Value;
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/Header.java b/core/java/com/android/internal/widget/remotecompose/core/operations/Header.java
index aabed15..9a1f37b 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/Header.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/Header.java
@@ -15,12 +15,16 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
-import com.android.internal.widget.remotecompose.core.CompanionOperation;
+import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT;
+import static com.android.internal.widget.remotecompose.core.documentation.Operation.LONG;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteComposeOperation;
import com.android.internal.widget.remotecompose.core.RemoteContext;
import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentedCompanionOperation;
import java.util.List;
@@ -41,6 +45,8 @@
int mWidth;
int mHeight;
+
+ float mDensity;
long mCapabilities;
public static final Companion COMPANION = new Companion();
@@ -54,21 +60,23 @@
* @param patchVersion the patch version of the RemoteCompose document API
* @param width the width of the RemoteCompose document
* @param height the height of the RemoteCompose document
+ * @param density the density at which the document was originally created
* @param capabilities bitmask field storing needed capabilities (unused for now)
*/
public Header(int majorVersion, int minorVersion, int patchVersion,
- int width, int height, long capabilities) {
+ int width, int height, float density, long capabilities) {
this.mMajorVersion = majorVersion;
this.mMinorVersion = minorVersion;
this.mPatchVersion = patchVersion;
this.mWidth = width;
this.mHeight = height;
+ this.mDensity = density;
this.mCapabilities = capabilities;
}
@Override
public void write(WireBuffer buffer) {
- COMPANION.apply(buffer, mWidth, mHeight, mCapabilities);
+ COMPANION.apply(buffer, mWidth, mHeight, mDensity, mCapabilities);
}
@Override
@@ -88,7 +96,7 @@
return toString();
}
- public static class Companion implements CompanionOperation {
+ public static class Companion implements DocumentedCompanionOperation {
private Companion() {
}
@@ -102,13 +110,15 @@
return Operations.HEADER;
}
- public void apply(WireBuffer buffer, int width, int height, long capabilities) {
+ public void apply(WireBuffer buffer, int width, int height,
+ float density, long capabilities) {
buffer.start(Operations.HEADER);
buffer.writeInt(MAJOR_VERSION); // major version number of the protocol
buffer.writeInt(MINOR_VERSION); // minor version number of the protocol
buffer.writeInt(PATCH_VERSION); // patch version number of the protocol
buffer.writeInt(width);
buffer.writeInt(height);
+ // buffer.writeFloat(density);
buffer.writeLong(capabilities);
}
@@ -119,10 +129,26 @@
int patchVersion = buffer.readInt();
int width = buffer.readInt();
int height = buffer.readInt();
+ // float density = buffer.readFloat();
+ float density = 1f;
long capabilities = buffer.readLong();
Header header = new Header(majorVersion, minorVersion, patchVersion,
- width, height, capabilities);
+ width, height, density, capabilities);
operations.add(header);
}
+
+ @Override
+ public void documentation(DocumentationBuilder doc) {
+ doc.operation("Protocol Operations", id(), name())
+ .description("Document metadata, containing the version,"
+ + " original size & density, capabilities mask")
+ .field(INT, "MAJOR_VERSION", "Major version")
+ .field(INT, "MINOR_VERSION", "Minor version")
+ .field(INT, "PATCH_VERSION", "Patch version")
+ .field(INT, "WIDTH", "Major version")
+ .field(INT, "HEIGHT", "Major version")
+ // .field(FLOAT, "DENSITY", "Major version")
+ .field(LONG, "CAPABILITIES", "Major version");
+ }
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/Theme.java b/core/java/com/android/internal/widget/remotecompose/core/operations/Theme.java
index cbe9c12..f982997 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/Theme.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/Theme.java
@@ -15,12 +15,15 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
-import com.android.internal.widget.remotecompose.core.CompanionOperation;
+import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteComposeOperation;
import com.android.internal.widget.remotecompose.core.RemoteContext;
import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentedCompanionOperation;
import java.util.List;
@@ -70,12 +73,12 @@
return indent + toString();
}
- public static class Companion implements CompanionOperation {
+ public static class Companion implements DocumentedCompanionOperation {
private Companion() {}
@Override
public String name() {
- return "SetTheme";
+ return "Theme";
}
@Override
@@ -93,5 +96,15 @@
int theme = buffer.readInt();
operations.add(new Theme(theme));
}
+
+ @Override
+ public void documentation(DocumentationBuilder doc) {
+ doc.operation("Protocol Operations", id(), name())
+ .description("Set a theme")
+ .field(INT, "THEME", "theme id")
+ .possibleValues("UNSPECIFIED", Theme.UNSPECIFIED)
+ .possibleValues("DARK", Theme.DARK)
+ .possibleValues("LIGHT", Theme.LIGHT);
+ }
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java
new file mode 100644
index 0000000..ee2e11b
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java
@@ -0,0 +1,473 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.PaintOperation;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.operations.layout.animation.AnimateMeasure;
+import com.android.internal.widget.remotecompose.core.operations.layout.animation.AnimationSpec;
+import com.android.internal.widget.remotecompose.core.operations.layout.measure.ComponentMeasure;
+import com.android.internal.widget.remotecompose.core.operations.layout.measure.Measurable;
+import com.android.internal.widget.remotecompose.core.operations.layout.measure.MeasurePass;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ComponentModifiers;
+import com.android.internal.widget.remotecompose.core.operations.paint.PaintBundle;
+import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
+
+import java.util.ArrayList;
+
+/**
+ * Generic Component class
+ */
+public class Component extends PaintOperation implements Measurable {
+
+ protected int mComponentId = -1;
+ protected float mX;
+ protected float mY;
+ protected float mWidth;
+ protected float mHeight;
+ protected Component mParent;
+ protected int mAnimationId = -1;
+ public Visibility mVisibility = Visibility.VISIBLE;
+ public ArrayList<Operation> mList = new ArrayList<>();
+ public PaintOperation mPreTranslate;
+ public boolean mNeedsMeasure = true;
+ public boolean mNeedsRepaint = false;
+ public AnimateMeasure mAnimateMeasure;
+ public AnimationSpec mAnimationSpec = new AnimationSpec();
+ public boolean mFirstLayout = true;
+ PaintBundle mPaint = new PaintBundle();
+
+ public ArrayList<Operation> getList() {
+ return mList;
+ }
+ public float getX() {
+ return mX;
+ }
+ public float getY() {
+ return mY;
+ }
+ public float getWidth() {
+ return mWidth;
+ }
+ public float getHeight() {
+ return mHeight;
+ }
+ public int getComponentId() {
+ return mComponentId;
+ }
+
+ public int getAnimationId() {
+ return mAnimationId;
+ }
+
+ public Component getParent() {
+ return mParent;
+ }
+ public void setX(float value) {
+ mX = value;
+ }
+ public void setY(float value) {
+ mY = value;
+ }
+ public void setWidth(float value) {
+ mWidth = value;
+ }
+ public void setHeight(float value) {
+ mHeight = value;
+ }
+
+ public void setComponentId(int id) {
+ mComponentId = id;
+ }
+
+ public void setAnimationId(int id) {
+ mAnimationId = id;
+ }
+
+ public Component(Component parent, int componentId, int animationId,
+ float x, float y, float width, float height) {
+ this.mComponentId = componentId;
+ this.mX = x;
+ this.mY = y;
+ this.mWidth = width;
+ this.mHeight = height;
+ this.mParent = parent;
+ this.mAnimationId = animationId;
+ }
+
+ public Component(int componentId, float x, float y, float width, float height,
+ Component parent) {
+ this(parent, componentId, -1, x, y, width, height);
+ }
+
+ public Component(Component component) {
+ this(component.mParent, component.mComponentId, component.mAnimationId,
+ component.mX, component.mY, component.mWidth, component.mHeight
+ );
+ mList.addAll(component.mList);
+ finalizeCreation();
+ }
+
+ public void finalizeCreation() {
+ for (Operation op : mList) {
+ if (op instanceof Component) {
+ ((Component) op).mParent = this;
+ }
+ if (op instanceof AnimationSpec) {
+ mAnimationSpec = (AnimationSpec) op;
+ mAnimationId = mAnimationSpec.getAnimationId();
+ }
+ }
+ }
+
+ @Override
+ public boolean needsMeasure() {
+ return mNeedsMeasure;
+ }
+
+ public void setParent(Component parent) {
+ mParent = parent;
+ }
+
+ public enum Visibility {
+ VISIBLE,
+ INVISIBLE,
+ GONE
+ }
+
+ public boolean isVisible() {
+ if (mVisibility != Visibility.VISIBLE || mParent == null) {
+ return mVisibility == Visibility.VISIBLE;
+ }
+ if (mParent != null) {
+ return mParent.isVisible();
+ }
+ return true;
+ }
+
+ @Override
+ public void measure(PaintContext context, float minWidth, float maxWidth,
+ float minHeight, float maxHeight, MeasurePass measure) {
+ ComponentMeasure m = measure.get(this);
+ m.setW(mWidth);
+ m.setH(mHeight);
+ }
+
+ @Override
+ public void layout(RemoteContext context, MeasurePass measure) {
+ ComponentMeasure m = measure.get(this);
+ if (!mFirstLayout && context.isAnimationEnabled()) {
+ if (mAnimateMeasure == null) {
+ ComponentMeasure origin = new ComponentMeasure(mComponentId,
+ mX, mY, mWidth, mHeight, mVisibility);
+ ComponentMeasure target = new ComponentMeasure(mComponentId,
+ m.getX(), m.getY(), m.getW(), m.getH(), m.getVisibility());
+ mAnimateMeasure = new AnimateMeasure(context.currentTime, this,
+ origin, target,
+ mAnimationSpec.getMotionDuration(), mAnimationSpec.getVisibilityDuration(),
+ mAnimationSpec.getEnterAnimation(), mAnimationSpec.getExitAnimation(),
+ mAnimationSpec.getMotionEasingType(),
+ mAnimationSpec.getVisibilityEasingType());
+ } else {
+ mAnimateMeasure.updateTarget(m, context.currentTime);
+ }
+ } else {
+ mVisibility = m.getVisibility();
+ }
+ mWidth = m.getW();
+ mHeight = m.getH();
+ setLayoutPosition(m.getX(), m.getY());
+ mFirstLayout = false;
+ }
+
+ public float[] locationInWindow = new float[2];
+
+ public boolean contains(float x, float y) {
+ locationInWindow[0] = 0f;
+ locationInWindow[1] = 0f;
+ getLocationInWindow(locationInWindow);
+ float lx1 = locationInWindow[0];
+ float lx2 = lx1 + mWidth;
+ float ly1 = locationInWindow[1];
+ float ly2 = ly1 + mHeight;
+ return x >= lx1 && x < lx2 && y >= ly1 && y < ly2;
+ }
+
+ public void onClick(float x, float y) {
+ if (!contains(x, y)) {
+ return;
+ }
+ for (Operation op : mList) {
+ if (op instanceof Component) {
+ ((Component) op).onClick(x, y);
+ }
+ if (op instanceof ComponentModifiers) {
+ ((ComponentModifiers) op).onClick(x, y);
+ }
+ }
+ }
+
+ public void getLocationInWindow(float[] value) {
+ value[0] += mX;
+ value[1] += mY;
+ if (mParent != null && mParent instanceof Component) {
+ if (mParent instanceof LayoutComponent) {
+ value[0] += ((LayoutComponent) mParent).getMarginLeft();
+ value[1] += ((LayoutComponent) mParent).getMarginTop();
+ }
+ mParent.getLocationInWindow(value);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "COMPONENT(<" + mComponentId + "> " + getClass().getSimpleName()
+ + ") [" + mX + "," + mY + " - " + mWidth + " x " + mHeight + "] " + textContent()
+ + " Visibility (" + mVisibility + ") ";
+ }
+
+ protected String getSerializedName() {
+ return "COMPONENT";
+ }
+
+ public void serializeToString(int indent, StringSerializer serializer) {
+ serializer.append(indent, getSerializedName() + " [" + mComponentId
+ + ":" + mAnimationId + "] = "
+ + "[" + mX + ", " + mY + ", " + mWidth + ", " + mHeight + "] "
+ + mVisibility
+ // + " [" + mNeedsMeasure + ", " + mNeedsRepaint + "]"
+ );
+ }
+
+ @Override
+ public void write(WireBuffer buffer) {
+ // nothing
+ }
+
+ /**
+ * Returns the top-level RootLayoutComponent
+ */
+ public RootLayoutComponent getRoot() throws Exception {
+ if (this instanceof RootLayoutComponent) {
+ return (RootLayoutComponent) this;
+ }
+ Component p = mParent;
+ while (!(p instanceof RootLayoutComponent)) {
+ if (p == null) {
+ throw new Exception("No RootLayoutComponent found");
+ }
+ p = p.mParent;
+ }
+ return (RootLayoutComponent) p;
+ }
+
+ @Override
+ public String deepToString(String indent) {
+ StringBuilder builder = new StringBuilder();
+ builder.append(indent);
+ builder.append(toString());
+ builder.append("\n");
+ String indent2 = " " + indent;
+ for (Operation op : mList) {
+ builder.append(op.deepToString(indent2));
+ builder.append("\n");
+ }
+ return builder.toString();
+ }
+
+ /**
+ * Mark itself as needing to be remeasured, and walk back up the tree
+ * to mark each parents as well.
+ */
+ public void invalidateMeasure() {
+ needsRepaint();
+ mNeedsMeasure = true;
+ Component p = mParent;
+ while (p != null) {
+ p.mNeedsMeasure = true;
+ p = p.mParent;
+ }
+ }
+
+ public void needsRepaint() {
+ try {
+ getRoot().mNeedsRepaint = true;
+ } catch (Exception e) {
+ // nothing
+ }
+ }
+
+ public String content() {
+ StringBuilder builder = new StringBuilder();
+ for (Operation op : mList) {
+ builder.append("- ");
+ builder.append(op);
+ builder.append("\n");
+ }
+ return builder.toString();
+ }
+
+ public String textContent() {
+ StringBuilder builder = new StringBuilder();
+ for (Operation op : mList) {
+ String letter = "";
+ // if (op instanceof DrawTextRun) {
+ // letter = "[" + ((DrawTextRun) op).text + "]";
+ // }
+ builder.append(letter);
+ }
+ return builder.toString();
+ }
+
+ public void debugBox(Component component, PaintContext context) {
+ float width = component.mWidth;
+ float height = component.mHeight;
+
+ context.savePaint();
+ mPaint.reset();
+ mPaint.setColor(0, 0, 255, 255); // Blue color
+ context.applyPaint(mPaint);
+ context.drawLine(0f, 0f, width, 0f);
+ context.drawLine(width, 0f, width, height);
+ context.drawLine(width, height, 0f, height);
+ context.drawLine(0f, height, 0f, 0f);
+ // context.setColor(255, 0, 0, 255)
+ // context.drawLine(0f, 0f, width, height)
+ // context.drawLine(0f, height, width, 0f)
+ context.restorePaint();
+ }
+
+ public void setLayoutPosition(float x, float y) {
+ this.mX = x;
+ this.mY = y;
+ }
+
+ public float getTranslateX() {
+ if (mParent != null) {
+ return mX - mParent.mX;
+ }
+ return 0f;
+ }
+
+ public float getTranslateY() {
+ if (mParent != null) {
+ return mY - mParent.mY;
+ }
+ return 0f;
+ }
+
+ public void paintingComponent(PaintContext context) {
+ if (mPreTranslate != null) {
+ mPreTranslate.paint(context);
+ }
+ context.save();
+ context.translate(mX, mY);
+ if (context.isDebug()) {
+ debugBox(this, context);
+ }
+ for (Operation op : mList) {
+ if (op instanceof PaintOperation) {
+ ((PaintOperation) op).paint(context);
+ }
+ }
+ context.restore();
+ }
+
+ public boolean applyAnimationAsNeeded(PaintContext context) {
+ if (context.isAnimationEnabled() && mAnimateMeasure != null) {
+ mAnimateMeasure.apply(context);
+ needsRepaint();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void paint(PaintContext context) {
+ if (context.isDebug()) {
+ context.save();
+ context.translate(mX, mY);
+ context.savePaint();
+ mPaint.reset();
+ mPaint.setColor(0, 255, 0, 255); // Green
+ context.applyPaint(mPaint);
+ context.drawLine(0f, 0f, mWidth, 0f);
+ context.drawLine(mWidth, 0f, mWidth, mHeight);
+ context.drawLine(mWidth, mHeight, 0f, mHeight);
+ context.drawLine(0f, mHeight, 0f, 0f);
+ mPaint.setColor(255, 0, 0, 255); // Red
+ context.applyPaint(mPaint);
+ context.drawLine(0f, 0f, mWidth, mHeight);
+ context.drawLine(0f, mHeight, mWidth, 0f);
+ context.restorePaint();
+ context.restore();
+ }
+ if (applyAnimationAsNeeded(context)) {
+ return;
+ }
+ if (mVisibility == Visibility.GONE) {
+ return;
+ }
+ paintingComponent(context);
+ }
+
+ public void getComponents(ArrayList<Component> components) {
+ for (Operation op : mList) {
+ if (op instanceof Component) {
+ components.add((Component) op);
+ }
+ }
+ }
+
+ public int getComponentCount() {
+ int count = 0;
+ for (Operation op : mList) {
+ if (op instanceof Component) {
+ count += 1 + ((Component) op).getComponentCount();
+ }
+ }
+ return count;
+ }
+
+ public int getPaintId() {
+ if (mAnimationId != -1) {
+ return mAnimationId;
+ }
+ return mComponentId;
+ }
+
+ public boolean doesNeedsRepaint() {
+ return mNeedsRepaint;
+ }
+
+ public Component getComponent(int cid) {
+ if (mComponentId == cid || mAnimationId == cid) {
+ return this;
+ }
+ for (Operation c : mList) {
+ if (c instanceof Component) {
+ Component search = ((Component) c).getComponent(cid);
+ if (search != null) {
+ return search;
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentEnd.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentEnd.java
new file mode 100644
index 0000000..8a523a2
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentEnd.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentedCompanionOperation;
+
+import java.util.List;
+
+public class ComponentEnd implements Operation {
+
+ public static final ComponentEnd.Companion COMPANION = new ComponentEnd.Companion();
+
+ @Override
+ public void write(WireBuffer buffer) {
+ Companion.apply(buffer);
+ }
+
+ @Override
+ public String toString() {
+ return "COMPONENT_END";
+ }
+
+ @Override
+ public void apply(RemoteContext context) {
+ // nothing
+ }
+
+ @Override
+ public String deepToString(String indent) {
+ return (indent != null ? indent : "") + toString();
+ }
+
+ public static class Companion implements DocumentedCompanionOperation {
+ @Override
+ public String name() {
+ return "ComponentEnd";
+ }
+
+ @Override
+ public int id() {
+ return Operations.COMPONENT_END;
+ }
+
+ public static void apply(WireBuffer buffer) {
+ buffer.start(Operations.COMPONENT_END);
+ }
+
+ public static int size() {
+ return 1 + 4 + 4 + 4;
+ }
+
+ @Override
+ public void read(WireBuffer buffer, List<Operation> operations) {
+ operations.add(new ComponentEnd());
+ }
+
+ @Override
+ public void documentation(DocumentationBuilder doc) {
+ doc.operation("Layout Operations", id(), name())
+ .description("End tag for components / layouts. This operation marks the end"
+ + "of a component");
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStart.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStart.java
new file mode 100644
index 0000000..5cfad25
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStart.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout;
+
+import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT;
+import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentedCompanionOperation;
+
+import java.util.List;
+
+public class ComponentStart implements ComponentStartOperation {
+
+ public static final ComponentStart.Companion COMPANION = new ComponentStart.Companion();
+
+ int mType = DEFAULT;
+ float mX;
+ float mY;
+ float mWidth;
+ float mHeight;
+ int mComponentId;
+
+ public int getType() {
+ return mType;
+ }
+
+ public float getX() {
+ return mX;
+ }
+
+ public float getY() {
+ return mY;
+ }
+
+ public float getWidth() {
+ return mWidth;
+ }
+
+ public float getHeight() {
+ return mHeight;
+ }
+
+ public int getComponentId() {
+ return mComponentId;
+ }
+
+ public ComponentStart(int type, int componentId, float width, float height) {
+ this.mType = type;
+ this.mComponentId = componentId;
+ this.mX = 0f;
+ this.mY = 0f;
+ this.mWidth = width;
+ this.mHeight = height;
+ }
+
+ @Override
+ public void write(WireBuffer buffer) {
+ Companion.apply(buffer, mType, mComponentId, mWidth, mHeight);
+ }
+
+ @Override
+ public String toString() {
+ return "COMPONENT_START (type " + mType + " " + Companion.typeDescription(mType)
+ + ") - (" + mX + ", " + mY + " - " + mWidth + " x " + mHeight + ")";
+ }
+
+ @Override
+ public String deepToString(String indent) {
+ return (indent != null ? indent : "") + toString();
+ }
+
+ @Override
+ public void apply(RemoteContext context) {
+ // nothing
+ }
+
+ public static final int UNKNOWN = -1;
+ public static final int DEFAULT = 0;
+ public static final int ROOT_LAYOUT = 1;
+ public static final int LAYOUT = 2;
+ public static final int LAYOUT_CONTENT = 3;
+ public static final int SCROLL_CONTENT = 4;
+ public static final int BUTTON = 5;
+ public static final int CHECKBOX = 6;
+ public static final int TEXT = 7;
+ public static final int CURVED_TEXT = 8;
+ public static final int STATE_HOST = 9;
+ public static final int CUSTOM = 10;
+ public static final int LOTTIE = 11;
+ public static final int IMAGE = 12;
+ public static final int STATE_BOX_CONTENT = 13;
+ public static final int LAYOUT_BOX = 14;
+ public static final int LAYOUT_ROW = 15;
+ public static final int LAYOUT_COLUMN = 16;
+
+ public static class Companion implements DocumentedCompanionOperation {
+
+
+ public static String typeDescription(int type) {
+ switch (type) {
+ case DEFAULT:
+ return "DEFAULT";
+ case ROOT_LAYOUT:
+ return "ROOT_LAYOUT";
+ case LAYOUT:
+ return "LAYOUT";
+ case LAYOUT_CONTENT:
+ return "CONTENT";
+ case SCROLL_CONTENT:
+ return "SCROLL_CONTENT";
+ case BUTTON:
+ return "BUTTON";
+ case CHECKBOX:
+ return "CHECKBOX";
+ case TEXT:
+ return "TEXT";
+ case CURVED_TEXT:
+ return "CURVED_TEXT";
+ case STATE_HOST:
+ return "STATE_HOST";
+ case LOTTIE:
+ return "LOTTIE";
+ case CUSTOM:
+ return "CUSTOM";
+ case IMAGE:
+ return "IMAGE";
+ default:
+ return "UNKNOWN";
+ }
+ }
+
+ @Override
+ public String name() {
+ return "ComponentStart";
+ }
+
+ @Override
+ public int id() {
+ return Operations.COMPONENT_START;
+ }
+
+ public static void apply(WireBuffer buffer, int type, int componentId,
+ float width, float height) {
+ buffer.start(Operations.COMPONENT_START);
+ buffer.writeInt(type);
+ buffer.writeInt(componentId);
+ buffer.writeFloat(width);
+ buffer.writeFloat(height);
+ }
+
+ public static int size() {
+ return 1 + 4 + 4 + 4;
+ }
+
+ @Override
+ public void read(WireBuffer buffer, List<Operation> operations) {
+ int type = buffer.readInt();
+ int componentId = buffer.readInt();
+ float width = buffer.readFloat();
+ float height = buffer.readFloat();
+ operations.add(new ComponentStart(type, componentId, width, height));
+ }
+
+ @Override
+ public void documentation(DocumentationBuilder doc) {
+ doc.operation("Layout Operations", id(), name())
+ .description("Basic component encapsulating draw commands."
+ + "This is not resizable.")
+ .field(INT, "TYPE", "Type of components")
+ .field(INT, "COMPONENT_ID", "unique id for this component")
+ .field(FLOAT, "WIDTH", "width of the component")
+ .field(FLOAT, "HEIGHT", "height of the component");
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStartOperation.java
similarity index 68%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
copy to core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStartOperation.java
index 1f04a44..67964ef 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStartOperation.java
@@ -13,13 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.internal.widget.remotecompose.core.operations.layout;
-package com.android.systemui.activatable
+import com.android.internal.widget.remotecompose.core.Operation;
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.TestScope
-
-/** Activates [activatable] for the duration of the test. */
-fun Activatable.activateIn(testScope: TestScope) {
- testScope.backgroundScope.launch { activate() }
+public interface ComponentStartOperation extends Operation {
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/DecoratorComponent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/DecoratorComponent.java
new file mode 100644
index 0000000..941666a
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/DecoratorComponent.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout;
+
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+
+/**
+ * Indicates a lightweight component (without children) that is only laid out and not able to be
+ * measured. Eg borders, background, clips, etc.
+ */
+public interface DecoratorComponent {
+ void layout(RemoteContext context, float width, float height);
+ void onClick(float x, float y);
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java
new file mode 100644
index 0000000..f198c4a
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ComponentModifiers;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.DimensionModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.HeightModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.PaddingModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.WidthModifierOperation;
+
+import java.util.ArrayList;
+
+/**
+ * Component with modifiers and children
+ */
+public class LayoutComponent extends Component {
+
+ protected WidthModifierOperation mWidthModifier = null;
+ protected HeightModifierOperation mHeightModifier = null;
+
+ // Margins
+ protected float mMarginLeft = 0f;
+ protected float mMarginRight = 0f;
+ protected float mMarginTop = 0f;
+ protected float mMarginBottom = 0f;
+
+ protected float mPaddingLeft = 0f;
+ protected float mPaddingRight = 0f;
+ protected float mPaddingTop = 0f;
+ protected float mPaddingBottom = 0f;
+
+ protected ComponentModifiers mComponentModifiers = new ComponentModifiers();
+ protected ArrayList<Component> mChildrenComponents = new ArrayList<>();
+
+ public LayoutComponent(Component parent, int componentId, int animationId,
+ float x, float y, float width, float height) {
+ super(parent, componentId, animationId, x, y, width, height);
+ }
+
+ public float getMarginLeft() {
+ return mMarginLeft;
+ }
+ public float getMarginRight() {
+ return mMarginRight;
+ }
+ public float getMarginTop() {
+ return mMarginTop;
+ }
+ public float getMarginBottom() {
+ return mMarginBottom;
+ }
+
+ public WidthModifierOperation getWidthModifier() {
+ return mWidthModifier;
+ }
+ public HeightModifierOperation getHeightModifier() {
+ return mHeightModifier;
+ }
+
+ public void inflate() {
+ for (Operation op : mList) {
+ if (op instanceof LayoutComponentContent) {
+ ((LayoutComponentContent) op).mParent = this;
+ mChildrenComponents.clear();
+ ((LayoutComponentContent) op).getComponents(mChildrenComponents);
+ if (mChildrenComponents.isEmpty()) {
+ mChildrenComponents.add((Component) op);
+ }
+ } else if (op instanceof ModifierOperation) {
+ mComponentModifiers.add((ModifierOperation) op);
+ } else {
+ // nothing
+ }
+ }
+
+ mList.clear();
+ mList.add(mComponentModifiers);
+ for (Component c : mChildrenComponents) {
+ c.mParent = this;
+ mList.add(c);
+ }
+
+ mX = 0f;
+ mY = 0f;
+ mMarginLeft = 0f;
+ mMarginTop = 0f;
+ mMarginRight = 0f;
+ mMarginBottom = 0f;
+ mPaddingLeft = 0f;
+ mPaddingTop = 0f;
+ mPaddingRight = 0f;
+ mPaddingBottom = 0f;
+
+ boolean applyHorizontalMargin = true;
+ boolean applyVerticalMargin = true;
+ for (Operation op : mComponentModifiers.getList()) {
+ if (op instanceof PaddingModifierOperation) {
+ // We are accumulating padding modifiers to compute the margin
+ // until we hit a dimension; the computed padding for the
+ // content simply accumulate all the padding modifiers.
+ float left = ((PaddingModifierOperation) op).getLeft();
+ float right = ((PaddingModifierOperation) op).getRight();
+ float top = ((PaddingModifierOperation) op).getTop();
+ float bottom = ((PaddingModifierOperation) op).getBottom();
+ if (applyHorizontalMargin) {
+ mMarginLeft += left;
+ mMarginRight += right;
+ }
+ if (applyVerticalMargin) {
+ mMarginTop += top;
+ mMarginBottom += bottom;
+ }
+ mPaddingLeft += left;
+ mPaddingTop += top;
+ mPaddingRight += right;
+ mPaddingBottom += bottom;
+ }
+ if (op instanceof WidthModifierOperation && mWidthModifier == null) {
+ mWidthModifier = (WidthModifierOperation) op;
+ applyHorizontalMargin = false;
+ }
+ if (op instanceof HeightModifierOperation && mHeightModifier == null) {
+ mHeightModifier = (HeightModifierOperation) op;
+ applyVerticalMargin = false;
+ }
+ }
+ if (mWidthModifier == null) {
+ mWidthModifier = new WidthModifierOperation(DimensionModifierOperation.Type.WRAP);
+ }
+ if (mHeightModifier == null) {
+ mHeightModifier = new HeightModifierOperation(DimensionModifierOperation.Type.WRAP);
+ }
+ mWidth = computeModifierDefinedWidth();
+ mHeight = computeModifierDefinedHeight();
+ }
+
+ @Override
+ public String toString() {
+ return "UNKNOWN LAYOUT_COMPONENT";
+ }
+
+ @Override
+ public void paintingComponent(PaintContext context) {
+ context.save();
+ context.translate(mX, mY);
+ mComponentModifiers.paint(context);
+ float tx = mPaddingLeft;
+ float ty = mPaddingTop;
+ context.translate(tx, ty);
+ for (Component child : mChildrenComponents) {
+ child.paint(context);
+ }
+ context.translate(-tx, -ty);
+ context.restore();
+ }
+
+ /**
+ * Traverse the modifiers to compute indicated dimension
+ */
+ public float computeModifierDefinedWidth() {
+ float s = 0f;
+ float e = 0f;
+ float w = 0f;
+ for (Operation c : mComponentModifiers.getList()) {
+ if (c instanceof WidthModifierOperation) {
+ WidthModifierOperation o = (WidthModifierOperation) c;
+ if (o.getType() == DimensionModifierOperation.Type.EXACT) {
+ w = o.getValue();
+ }
+ break;
+ }
+ if (c instanceof PaddingModifierOperation) {
+ PaddingModifierOperation pop = (PaddingModifierOperation) c;
+ s += pop.getLeft();
+ e += pop.getRight();
+ }
+ }
+ return s + w + e;
+ }
+
+ /**
+ * Traverse the modifiers to compute indicated dimension
+ */
+ public float computeModifierDefinedHeight() {
+ float t = 0f;
+ float b = 0f;
+ float h = 0f;
+ for (Operation c : mComponentModifiers.getList()) {
+ if (c instanceof HeightModifierOperation) {
+ HeightModifierOperation o = (HeightModifierOperation) c;
+ if (o.getType() == DimensionModifierOperation.Type.EXACT) {
+ h = o.getValue();
+ }
+ break;
+ }
+ if (c instanceof PaddingModifierOperation) {
+ PaddingModifierOperation pop = (PaddingModifierOperation) c;
+ t += pop.getTop();
+ b += pop.getBottom();
+ }
+ }
+ return t + h + b;
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponentContent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponentContent.java
new file mode 100644
index 0000000..769ff6a
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponentContent.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentedCompanionOperation;
+
+import java.util.List;
+
+/**
+ * Represents the content of a LayoutComponent (i.e. the children components)
+ */
+public class LayoutComponentContent extends Component implements ComponentStartOperation {
+
+ public static final LayoutComponentContent.Companion COMPANION =
+ new LayoutComponentContent.Companion();
+
+ public LayoutComponentContent(int componentId, float x, float y,
+ float width, float height, Component parent, int animationId) {
+ super(parent, componentId, animationId, x, y, width, height);
+ }
+
+ public static class Companion implements DocumentedCompanionOperation {
+ @Override
+ public String name() {
+ return "LayoutContent";
+ }
+
+ @Override
+ public int id() {
+ return Operations.LAYOUT_CONTENT;
+ }
+
+ public void apply(WireBuffer buffer) {
+ buffer.start(Operations.LAYOUT_CONTENT);
+ }
+
+ @Override
+ public void read(WireBuffer buffer, List<Operation> operations) {
+ operations.add(new LayoutComponentContent(
+ -1, 0, 0, 0, 0, null, -1));
+ }
+
+ @Override
+ public void documentation(DocumentationBuilder doc) {
+ doc.operation("Layout Operations", id(), name())
+ .description("Container for components. BoxLayout, RowLayout and ColumnLayout "
+ + "expects a LayoutComponentContent as a child, encapsulating the "
+ + "components that needs to be laid out.");
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java
new file mode 100644
index 0000000..dc13768
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.PaintOperation;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentedCompanionOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.measure.Measurable;
+import com.android.internal.widget.remotecompose.core.operations.layout.measure.MeasurePass;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ComponentModifiers;
+import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
+
+import java.util.List;
+
+/**
+ * Represents the root layout component. Entry point to the component tree layout/paint.
+ */
+public class RootLayoutComponent extends Component implements ComponentStartOperation {
+
+ public static final RootLayoutComponent.Companion COMPANION =
+ new RootLayoutComponent.Companion();
+
+ int mCurrentId = -1;
+
+ public RootLayoutComponent(int componentId, float x, float y,
+ float width, float height, Component parent, int animationId) {
+ super(parent, componentId, animationId, x, y, width, height);
+ }
+
+ public RootLayoutComponent(int componentId, float x, float y,
+ float width, float height, Component parent) {
+ super(parent, componentId, -1, x, y, width, height);
+ }
+
+ @Override
+ public String toString() {
+ return "ROOT (" + mX + ", " + mY + " - " + mWidth + " x " + mHeight + ") " + mVisibility;
+ }
+
+ @Override
+ public void serializeToString(int indent, StringSerializer serializer) {
+ serializer.append(indent, "ROOT [" + mComponentId + ":" + mAnimationId
+ + "] = [" + mX + ", " + mY + ", " + mWidth + ", " + mHeight + "] " + mVisibility);
+ }
+
+ public int getNextId() {
+ mCurrentId--;
+ return mCurrentId;
+ }
+
+ public void assignIds() {
+ assignId(this);
+ }
+
+ void assignId(Component component) {
+ if (component.mComponentId == -1) {
+ component.mComponentId = getNextId();
+ }
+ for (Operation op : component.mList) {
+ if (op instanceof Component) {
+ assignId((Component) op);
+ }
+ }
+ }
+
+ /**
+ * This will measure then layout the tree of components
+ */
+ public void layout(RemoteContext context) {
+ if (!mNeedsMeasure) {
+ return;
+ }
+ context.lastComponent = this;
+ mWidth = context.mWidth;
+ mHeight = context.mHeight;
+
+ // TODO: reuse MeasurePass
+ MeasurePass measurePass = new MeasurePass();
+ for (Operation op : mList) {
+ if (op instanceof Measurable) {
+ Measurable m = (Measurable) op;
+ m.measure(context.getPaintContext(),
+ 0f, mWidth, 0f, mHeight, measurePass);
+ m.layout(context, measurePass);
+ }
+ }
+ mNeedsMeasure = false;
+ }
+
+ @Override
+ public void paint(PaintContext context) {
+ mNeedsRepaint = false;
+ context.getContext().lastComponent = this;
+ context.save();
+
+ if (mParent == null) { // root layout
+ context.clipRect(0f, 0f, mWidth, mHeight);
+ }
+
+ for (Operation op : mList) {
+ if (op instanceof PaintOperation) {
+ ((PaintOperation) op).paint(context);
+ }
+ }
+
+ context.restore();
+ }
+
+ public String displayHierarchy() {
+ StringSerializer serializer = new StringSerializer();
+ displayHierarchy(this, 0, serializer);
+ return serializer.toString();
+ }
+
+ public void displayHierarchy(Component component, int indent, StringSerializer serializer) {
+ component.serializeToString(indent, serializer);
+ for (Operation c : component.mList) {
+ if (c instanceof ComponentModifiers) {
+ ((ComponentModifiers) c).serializeToString(indent + 1, serializer);
+ }
+ if (c instanceof Component) {
+ displayHierarchy((Component) c, indent + 1, serializer);
+ }
+ }
+ }
+
+ public static class Companion implements DocumentedCompanionOperation {
+ @Override
+ public String name() {
+ return "RootLayout";
+ }
+
+ @Override
+ public int id() {
+ return Operations.LAYOUT_ROOT;
+ }
+
+ public void apply(WireBuffer buffer) {
+ buffer.start(Operations.LAYOUT_ROOT);
+ }
+
+ @Override
+ public void read(WireBuffer buffer, List<Operation> operations) {
+ operations.add(new RootLayoutComponent(
+ -1, 0, 0, 0, 0, null, -1));
+ }
+
+ @Override
+ public void documentation(DocumentationBuilder doc) {
+ doc.operation("Layout Operations", id(), name())
+ .description("Root element for a document. Other components / layout managers "
+ + "are children in the component tree starting from this Root component.");
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimateMeasure.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimateMeasure.java
new file mode 100644
index 0000000..7c6bef4
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimateMeasure.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout.animation;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.operations.layout.Component;
+import com.android.internal.widget.remotecompose.core.operations.layout.DecoratorComponent;
+import com.android.internal.widget.remotecompose.core.operations.layout.measure.ComponentMeasure;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.PaddingModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.paint.PaintBundle;
+import com.android.internal.widget.remotecompose.core.operations.utilities.easing.FloatAnimation;
+import com.android.internal.widget.remotecompose.core.operations.utilities.easing.GeneralEasing;
+
+/**
+ * Basic interpolation manager between two ComponentMeasures
+ *
+ * Handles position, size and visibility
+ */
+public class AnimateMeasure {
+ long mStartTime = System.currentTimeMillis();
+ Component mComponent;
+ ComponentMeasure mOriginal;
+ ComponentMeasure mTarget;
+ int mDuration;
+ int mDurationVisibilityChange = mDuration;
+ AnimationSpec.ANIMATION mEnterAnimation = AnimationSpec.ANIMATION.FADE_IN;
+ AnimationSpec.ANIMATION mExitAnimation = AnimationSpec.ANIMATION.FADE_OUT;
+ int mMotionEasingType = GeneralEasing.CUBIC_STANDARD;
+ int mVisibilityEasingType = GeneralEasing.CUBIC_ACCELERATE;
+
+ float mP = 0f;
+ float mVp = 0f;
+ FloatAnimation mMotionEasing = new FloatAnimation(mMotionEasingType,
+ mDuration / 1000f, null, 0f, Float.NaN);
+ FloatAnimation mVisibilityEasing = new FloatAnimation(mVisibilityEasingType,
+ mDurationVisibilityChange / 1000f,
+ null, 0f, Float.NaN);
+ ParticleAnimation mParticleAnimation;
+
+ public AnimateMeasure(long startTime, Component component, ComponentMeasure original,
+ ComponentMeasure target, int duration, int durationVisibilityChange,
+ AnimationSpec.ANIMATION enterAnimation,
+ AnimationSpec.ANIMATION exitAnimation,
+ int motionEasingType, int visibilityEasingType) {
+ this.mStartTime = startTime;
+ this.mComponent = component;
+ this.mOriginal = original;
+ this.mTarget = target;
+ this.mDuration = duration;
+ this.mDurationVisibilityChange = durationVisibilityChange;
+ this.mEnterAnimation = enterAnimation;
+ this.mExitAnimation = exitAnimation;
+
+ mMotionEasing.setTargetValue(1f);
+ mVisibilityEasing.setTargetValue(1f);
+ component.mVisibility = target.getVisibility();
+ }
+
+ public void update(long currentTime) {
+ long elapsed = currentTime - mStartTime;
+ mP = Math.min(elapsed / (float) mDuration, 1f);
+ //mP = motionEasing.get(mP);
+ mVp = Math.min(elapsed / (float) mDurationVisibilityChange, 1f);
+ mVp = mVisibilityEasing.get(mVp);
+ }
+
+ public PaintBundle paint = new PaintBundle();
+
+ public void apply(PaintContext context) {
+ update(context.getContext().currentTime);
+
+ mComponent.setX(getX());
+ mComponent.setY(getY());
+ mComponent.setWidth(getWidth());
+ mComponent.setHeight(getHeight());
+
+ float w = mComponent.getWidth();
+ float h = mComponent.getHeight();
+ for (Operation op : mComponent.mList) {
+ if (op instanceof PaddingModifierOperation) {
+ PaddingModifierOperation pop = (PaddingModifierOperation) op;
+ w -= pop.getLeft() + pop.getRight();
+ h -= pop.getTop() + pop.getBottom();
+ }
+ if (op instanceof DecoratorComponent) {
+ ((DecoratorComponent) op).layout(context.getContext(), w, h);
+ }
+ }
+
+ mComponent.mVisibility = mTarget.getVisibility();
+ if (mOriginal.getVisibility() != mTarget.getVisibility()) {
+ if (mTarget.getVisibility() == Component.Visibility.GONE) {
+ switch (mExitAnimation) {
+ case PARTICLE:
+ // particleAnimation(context, component, original, target, vp)
+ if (mParticleAnimation == null) {
+ mParticleAnimation = new ParticleAnimation();
+ }
+ mParticleAnimation.animate(context, mComponent, mOriginal, mTarget, mVp);
+ break;
+ case FADE_OUT:
+ context.save();
+ context.savePaint();
+ paint.reset();
+ paint.setColor(0f, 0f, 0f, 1f - mVp);
+ context.applyPaint(paint);
+ context.saveLayer(mComponent.getX(), mComponent.getY(),
+ mComponent.getWidth(), mComponent.getHeight());
+ mComponent.paintingComponent(context);
+ context.restore();
+ context.restorePaint();
+ context.restore();
+ break;
+ case SLIDE_LEFT:
+ context.save();
+ context.translate(-mVp * mComponent.getParent().getWidth(), 0f);
+ context.saveLayer(mComponent.getX(), mComponent.getY(),
+ mComponent.getWidth(), mComponent.getHeight());
+ mComponent.paintingComponent(context);
+ context.restore();
+ context.restore();
+ break;
+ case SLIDE_RIGHT:
+ context.save();
+ context.savePaint();
+ paint.reset();
+ paint.setColor(0f, 0f, 0f, 1f);
+ context.applyPaint(paint);
+ context.translate(mVp * mComponent.getParent().getWidth(), 0f);
+ context.saveLayer(mComponent.getX(), mComponent.getY(),
+ mComponent.getWidth(), mComponent.getHeight());
+ mComponent.paintingComponent(context);
+ context.restore();
+ context.restorePaint();
+ context.restore();
+ break;
+ case SLIDE_TOP:
+ context.save();
+ context.translate(0f,
+ -mVp * mComponent.getParent().getHeight());
+ context.saveLayer(mComponent.getX(), mComponent.getY(),
+ mComponent.getWidth(), mComponent.getHeight());
+ mComponent.paintingComponent(context);
+ context.restore();
+ context.restore();
+ break;
+ case SLIDE_BOTTOM:
+ context.save();
+ context.translate(0f,
+ mVp * mComponent.getParent().getHeight());
+ context.saveLayer(mComponent.getX(), mComponent.getY(),
+ mComponent.getWidth(), mComponent.getHeight());
+ mComponent.paintingComponent(context);
+ context.restore();
+ context.restore();
+ break;
+ default:
+ // particleAnimation(context, component, original, target, vp)
+ if (mParticleAnimation == null) {
+ mParticleAnimation = new ParticleAnimation();
+ }
+ mParticleAnimation.animate(context, mComponent, mOriginal, mTarget, mVp);
+ break;
+ }
+ } else if (mOriginal.getVisibility() == Component.Visibility.GONE
+ && mTarget.getVisibility() == Component.Visibility.VISIBLE) {
+ switch (mEnterAnimation) {
+ case ROTATE:
+ float px = mTarget.getX() + mTarget.getW() / 2f;
+ float py = mTarget.getY() + mTarget.getH() / 2f;
+
+ context.save();
+ context.savePaint();
+ context.matrixRotate(mVp * 360f, px, py);
+ context.matrixScale(1f * mVp, 1f * mVp, px, py);
+ paint.reset();
+ paint.setColor(0f, 0f, 0f, mVp);
+ context.applyPaint(paint);
+ context.saveLayer(mComponent.getX(), mComponent.getY(),
+ mComponent.getWidth(), mComponent.getHeight());
+ mComponent.paintingComponent(context);
+ context.restore();
+ context.restorePaint();
+ context.restore();
+ break;
+ case FADE_IN:
+ context.save();
+ context.savePaint();
+ paint.reset();
+ paint.setColor(0f, 0f, 0f, mVp);
+ context.applyPaint(paint);
+ context.saveLayer(mComponent.getX(), mComponent.getY(),
+ mComponent.getWidth(), mComponent.getHeight());
+ mComponent.paintingComponent(context);
+ context.restore();
+ context.restorePaint();
+ context.restore();
+ break;
+ case SLIDE_LEFT:
+ context.save();
+ context.translate(
+ (1f - mVp) * mComponent.getParent().getWidth(), 0f);
+ context.saveLayer(mComponent.getX(), mComponent.getY(),
+ mComponent.getWidth(), mComponent.getHeight());
+ mComponent.paintingComponent(context);
+ context.restore();
+ context.restore();
+ break;
+ case SLIDE_RIGHT:
+ context.save();
+ context.translate(
+ -(1f - mVp) * mComponent.getParent().getWidth(), 0f);
+ context.saveLayer(mComponent.getX(), mComponent.getY(),
+ mComponent.getWidth(), mComponent.getHeight());
+ mComponent.paintingComponent(context);
+ context.restore();
+ context.restore();
+ break;
+ case SLIDE_TOP:
+ context.save();
+ context.translate(0f,
+ (1f - mVp) * mComponent.getParent().getHeight());
+ context.saveLayer(mComponent.getX(), mComponent.getY(),
+ mComponent.getWidth(), mComponent.getHeight());
+ mComponent.paintingComponent(context);
+ context.restore();
+ context.restore();
+ break;
+ case SLIDE_BOTTOM:
+ context.save();
+ context.translate(0f,
+ -(1f - mVp) * mComponent.getParent().getHeight());
+ context.saveLayer(mComponent.getX(), mComponent.getY(),
+ mComponent.getWidth(), mComponent.getHeight());
+ mComponent.paintingComponent(context);
+ context.restore();
+ context.restore();
+ break;
+ default:
+ break;
+ }
+ } else {
+ mComponent.paintingComponent(context);
+ }
+ } else {
+ mComponent.paintingComponent(context);
+ }
+
+ if (mP >= 1f && mVp >= 1f) {
+ mComponent.mAnimateMeasure = null;
+ mComponent.mVisibility = mTarget.getVisibility();
+ }
+ }
+
+ public boolean isDone() {
+ return mP >= 1f && mVp >= 1f;
+ }
+
+ public float getX() {
+ return mOriginal.getX() * (1 - mP) + mTarget.getX() * mP;
+ }
+
+ public float getY() {
+ return mOriginal.getY() * (1 - mP) + mTarget.getY() * mP;
+ }
+
+ public float getWidth() {
+ return mOriginal.getW() * (1 - mP) + mTarget.getW() * mP;
+ }
+
+ public float getHeight() {
+ return mOriginal.getH() * (1 - mP) + mTarget.getH() * mP;
+ }
+
+ public float getVisibility() {
+ if (mOriginal.getVisibility() == mTarget.getVisibility()) {
+ return 1f;
+ } else if (mTarget.getVisibility() == Component.Visibility.VISIBLE) {
+ return mVp;
+ } else {
+ return 1 - mVp;
+ }
+ }
+
+ public void updateTarget(ComponentMeasure measure, long currentTime) {
+ mOriginal.setX(getX());
+ mOriginal.setY(getY());
+ mOriginal.setW(getWidth());
+ mOriginal.setH(getHeight());
+ mTarget.setX(measure.getX());
+ mTarget.setY(measure.getY());
+ mTarget.setW(measure.getW());
+ mTarget.setH(measure.getH());
+ mTarget.setVisibility(measure.getVisibility());
+ mStartTime = currentTime;
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java
new file mode 100644
index 0000000..386d365
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout.animation;
+
+import com.android.internal.widget.remotecompose.core.CompanionOperation;
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.operations.utilities.easing.GeneralEasing;
+
+import java.util.List;
+
+/**
+ * Basic component animation spec
+ */
+public class AnimationSpec implements Operation {
+
+ public static final AnimationSpec.Companion COMPANION = new AnimationSpec.Companion();
+
+ int mAnimationId = -1;
+ int mMotionDuration = 300;
+ int mMotionEasingType = GeneralEasing.CUBIC_STANDARD;
+ int mVisibilityDuration = 300;
+ int mVisibilityEasingType = GeneralEasing.CUBIC_STANDARD;
+ ANIMATION mEnterAnimation = ANIMATION.FADE_IN;
+ ANIMATION mExitAnimation = ANIMATION.FADE_OUT;
+
+ public AnimationSpec(int animationId, int motionDuration, int motionEasingType,
+ int visibilityDuration, int visibilityEasingType,
+ ANIMATION enterAnimation, ANIMATION exitAnimation) {
+ this.mAnimationId = animationId;
+ this.mMotionDuration = motionDuration;
+ this.mMotionEasingType = motionEasingType;
+ this.mVisibilityDuration = visibilityDuration;
+ this.mVisibilityEasingType = visibilityEasingType;
+ this.mEnterAnimation = enterAnimation;
+ this.mExitAnimation = exitAnimation;
+ }
+
+ public AnimationSpec() {
+ this(-1, 300, GeneralEasing.CUBIC_STANDARD,
+ 300, GeneralEasing.CUBIC_STANDARD,
+ ANIMATION.FADE_IN, ANIMATION.FADE_OUT);
+ }
+
+ public int getAnimationId() {
+ return mAnimationId;
+ }
+
+ public int getMotionDuration() {
+ return mMotionDuration;
+ }
+
+ public int getMotionEasingType() {
+ return mMotionEasingType;
+ }
+
+ public int getVisibilityDuration() {
+ return mVisibilityDuration;
+ }
+
+ public int getVisibilityEasingType() {
+ return mVisibilityEasingType;
+ }
+
+ public ANIMATION getEnterAnimation() {
+ return mEnterAnimation;
+ }
+
+ public ANIMATION getExitAnimation() {
+ return mExitAnimation;
+ }
+
+ @Override
+ public String toString() {
+ return "ANIMATION_SPEC (" + mMotionDuration + " ms)";
+ }
+
+ public enum ANIMATION {
+ FADE_IN,
+ FADE_OUT,
+ SLIDE_LEFT,
+ SLIDE_RIGHT,
+ SLIDE_TOP,
+ SLIDE_BOTTOM,
+ ROTATE,
+ PARTICLE
+ }
+
+ @Override
+ public void write(WireBuffer buffer) {
+ Companion.apply(buffer, mAnimationId, mMotionDuration, mMotionEasingType,
+ mVisibilityDuration, mVisibilityEasingType, mEnterAnimation, mExitAnimation);
+ }
+
+ @Override
+ public void apply(RemoteContext context) {
+ // nothing here
+ }
+
+ @Override
+ public String deepToString(String indent) {
+ return (indent != null ? indent : "") + toString();
+ }
+
+ public static class Companion implements CompanionOperation {
+ @Override
+ public String name() {
+ return "AnimationSpec";
+ }
+
+ @Override
+ public int id() {
+ return Operations.ANIMATION_SPEC;
+ }
+
+ public static int animationToInt(ANIMATION animation) {
+ return animation.ordinal();
+ }
+
+ public static ANIMATION intToAnimation(int value) {
+ switch (value) {
+ case 0:
+ return ANIMATION.FADE_IN;
+ case 1:
+ return ANIMATION.FADE_OUT;
+ case 2:
+ return ANIMATION.SLIDE_LEFT;
+ case 3:
+ return ANIMATION.SLIDE_RIGHT;
+ case 4:
+ return ANIMATION.SLIDE_TOP;
+ case 5:
+ return ANIMATION.SLIDE_BOTTOM;
+ case 6:
+ return ANIMATION.ROTATE;
+ case 7:
+ return ANIMATION.PARTICLE;
+ default:
+ return ANIMATION.FADE_IN;
+ }
+ }
+
+ public static void apply(WireBuffer buffer, int animationId, int motionDuration,
+ int motionEasingType, int visibilityDuration,
+ int visibilityEasingType, ANIMATION enterAnimation,
+ ANIMATION exitAnimation) {
+ buffer.start(Operations.ANIMATION_SPEC);
+ buffer.writeInt(animationId);
+ buffer.writeInt(motionDuration);
+ buffer.writeInt(motionEasingType);
+ buffer.writeInt(visibilityDuration);
+ buffer.writeInt(visibilityEasingType);
+ buffer.writeInt(animationToInt(enterAnimation));
+ buffer.writeInt(animationToInt(exitAnimation));
+ }
+
+ @Override
+ public void read(WireBuffer buffer, List<Operation> operations) {
+ int animationId = buffer.readInt();
+ int motionDuration = buffer.readInt();
+ int motionEasingType = buffer.readInt();
+ int visibilityDuration = buffer.readInt();
+ int visibilityEasingType = buffer.readInt();
+ ANIMATION enterAnimation = intToAnimation(buffer.readInt());
+ ANIMATION exitAnimation = intToAnimation(buffer.readInt());
+ AnimationSpec op = new AnimationSpec(animationId, motionDuration, motionEasingType,
+ visibilityDuration, visibilityEasingType, enterAnimation, exitAnimation);
+ operations.add(op);
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/Particle.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/Particle.java
new file mode 100644
index 0000000..4562692
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/Particle.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout.animation;
+
+public class Particle {
+ public final float x;
+ public final float y;
+ public float radius;
+ public float r;
+ public float g;
+ public float b;
+
+ public Particle(float x, float y, float radius, float r, float g, float b) {
+ this.x = x;
+ this.y = y;
+ this.radius = radius;
+ this.r = r;
+ this.g = g;
+ this.b = b;
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/ParticleAnimation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/ParticleAnimation.java
new file mode 100644
index 0000000..5c5d056
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/ParticleAnimation.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout.animation;
+
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.operations.layout.Component;
+import com.android.internal.widget.remotecompose.core.operations.layout.measure.ComponentMeasure;
+import com.android.internal.widget.remotecompose.core.operations.paint.PaintBundle;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class ParticleAnimation {
+ HashMap<Integer, ArrayList<Particle>> mAllParticles = new HashMap<>();
+
+ PaintBundle mPaint = new PaintBundle();
+ public void animate(PaintContext context, Component component,
+ ComponentMeasure start, ComponentMeasure end,
+ float progress) {
+ ArrayList<Particle> particles = mAllParticles.get(component.getComponentId());
+ if (particles == null) {
+ particles = new ArrayList<Particle>();
+ for (int i = 0; i < 20; i++) {
+ float x = (float) Math.random();
+ float y = (float) Math.random();
+ float radius = (float) Math.random();
+ float r = 250f;
+ float g = 250f;
+ float b = 250f;
+ particles.add(new Particle(x, y, radius, r, g, b));
+ }
+ mAllParticles.put(component.getComponentId(), particles);
+ }
+ context.save();
+ context.savePaint();
+ for (int i = 0; i < particles.size(); i++) {
+ Particle particle = particles.get(i);
+ mPaint.reset();
+ mPaint.setColor(particle.r, particle.g, particle.b,
+ 200 * (1 - progress));
+ context.applyPaint(mPaint);
+ float dx = start.getX() + component.getWidth() * particle.x;
+ float dy = start.getY() + component.getHeight() * particle.y
+ + progress * 0.01f * component.getHeight();
+ float dr = (component.getHeight() + 60) * 0.15f * particle.radius + (30 * progress);
+ context.drawCircle(dx, dy, dr);
+ }
+ context.restorePaint();
+ context.restore();
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java
new file mode 100644
index 0000000..fea8dd2
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.widget.remotecompose.core.operations.layout.managers;
+
+import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentedCompanionOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.Component;
+import com.android.internal.widget.remotecompose.core.operations.layout.ComponentStartOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.measure.ComponentMeasure;
+import com.android.internal.widget.remotecompose.core.operations.layout.measure.MeasurePass;
+import com.android.internal.widget.remotecompose.core.operations.layout.measure.Size;
+
+import java.util.List;
+
+/**
+ * Simple Box layout implementation
+ */
+public class BoxLayout extends LayoutManager implements ComponentStartOperation {
+
+ public static final int START = 1;
+ public static final int CENTER = 2;
+ public static final int END = 3;
+ public static final int TOP = 4;
+ public static final int BOTTOM = 5;
+
+ public static final BoxLayout.Companion COMPANION = new BoxLayout.Companion();
+
+ int mHorizontalPositioning;
+ int mVerticalPositioning;
+
+ public BoxLayout(Component parent, int componentId, int animationId,
+ float x, float y, float width, float height,
+ int horizontalPositioning, int verticalPositioning) {
+ super(parent, componentId, animationId, x, y, width, height);
+ mHorizontalPositioning = horizontalPositioning;
+ mVerticalPositioning = verticalPositioning;
+ }
+
+ public BoxLayout(Component parent, int componentId, int animationId,
+ int horizontalPositioning, int verticalPositioning) {
+ this(parent, componentId, animationId, 0, 0, 0, 0,
+ horizontalPositioning, verticalPositioning);
+ }
+
+ @Override
+ public String toString() {
+ return "BOX [" + mComponentId + ":" + mAnimationId + "] (" + mX + ", "
+ + mY + " - " + mWidth + " x " + mHeight + ") " + mVisibility;
+ }
+
+ protected String getSerializedName() {
+ return "BOX";
+ }
+
+ @Override
+ public void computeWrapSize(PaintContext context, float maxWidth, float maxHeight,
+ MeasurePass measure, Size size) {
+ for (Component c : mChildrenComponents) {
+ c.measure(context, 0f, maxWidth, 0f, maxHeight, measure);
+ ComponentMeasure m = measure.get(c);
+ size.setWidth(Math.max(size.getWidth(), m.getW()));
+ size.setHeight(Math.max(size.getHeight(), m.getH()));
+ }
+ // add padding
+ size.setWidth(Math.max(size.getWidth(), computeModifierDefinedWidth()));
+ size.setHeight(Math.max(size.getHeight(), computeModifierDefinedHeight()));
+ }
+
+ @Override
+ public void computeSize(PaintContext context, float minWidth, float maxWidth,
+ float minHeight, float maxHeight, MeasurePass measure) {
+ for (Component child : mChildrenComponents) {
+ child.measure(context, minWidth, maxWidth, minHeight, maxHeight, measure);
+ }
+ }
+
+ @Override
+ public void internalLayoutMeasure(PaintContext context,
+ MeasurePass measure) {
+ ComponentMeasure selfMeasure = measure.get(this);
+ float selfWidth = selfMeasure.getW() - mPaddingLeft - mPaddingRight;
+ float selfHeight = selfMeasure.getH() - mPaddingTop - mPaddingBottom;
+ for (Component child : mChildrenComponents) {
+ ComponentMeasure m = measure.get(child);
+ float tx = 0f;
+ float ty = 0f;
+ switch (mVerticalPositioning) {
+ case TOP:
+ ty = 0f;
+ break;
+ case CENTER:
+ ty = (selfHeight - m.getH()) / 2f;
+ break;
+ case BOTTOM:
+ ty = selfHeight - m.getH();
+ break;
+ }
+ switch (mHorizontalPositioning) {
+ case START:
+ tx = 0f;
+ break;
+ case CENTER:
+ tx = (selfWidth - m.getW()) / 2f;
+ break;
+ case END:
+ tx = selfWidth - m.getW();
+ break;
+ }
+ m.setX(tx);
+ m.setY(ty);
+ m.setVisibility(child.mVisibility);
+ }
+ }
+
+ public static class Companion implements DocumentedCompanionOperation {
+ @Override
+ public String name() {
+ return "BoxLayout";
+ }
+
+ @Override
+ public int id() {
+ return Operations.LAYOUT_BOX;
+ }
+
+ public void apply(WireBuffer buffer, int componentId, int animationId,
+ int horizontalPositioning, int verticalPositioning) {
+ buffer.start(Operations.LAYOUT_BOX);
+ buffer.writeInt(componentId);
+ buffer.writeInt(animationId);
+ buffer.writeInt(horizontalPositioning);
+ buffer.writeInt(verticalPositioning);
+ }
+
+ @Override
+ public void read(WireBuffer buffer, List<Operation> operations) {
+ int componentId = buffer.readInt();
+ int animationId = buffer.readInt();
+ int horizontalPositioning = buffer.readInt();
+ int verticalPositioning = buffer.readInt();
+ operations.add(new BoxLayout(null, componentId, animationId,
+ horizontalPositioning, verticalPositioning));
+ }
+
+ @Override
+ public void documentation(DocumentationBuilder doc) {
+ doc.operation("Layout Operations", id(), name())
+ .description("Box layout implementation.\n\n"
+ + "Child components are laid out independently from one another,\n"
+ + " and painted in their hierarchy order (first children drawn"
+ + "before the latter). Horizontal and Vertical positioning"
+ + "are supported.")
+ .examplesDimension(150, 100)
+ .exampleImage("Top", "layout-BoxLayout-start-top.png")
+ .exampleImage("Center", "layout-BoxLayout-center-center.png")
+ .exampleImage("Bottom", "layout-BoxLayout-end-bottom.png")
+ .field(INT, "COMPONENT_ID", "unique id for this component")
+ .field(INT, "ANIMATION_ID", "id used to match components,"
+ + " for animation purposes")
+ .field(INT, "HORIZONTAL_POSITIONING", "horizontal positioning value")
+ .possibleValues("START", BoxLayout.START)
+ .possibleValues("CENTER", BoxLayout.CENTER)
+ .possibleValues("END", BoxLayout.END)
+ .field(INT, "VERTICAL_POSITIONING", "vertical positioning value")
+ .possibleValues("TOP", BoxLayout.TOP)
+ .possibleValues("CENTER", BoxLayout.CENTER)
+ .possibleValues("BOTTOM", BoxLayout.BOTTOM);
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java
new file mode 100644
index 0000000..a1a2de5
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout.managers;
+
+import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT;
+import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentedCompanionOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.Component;
+import com.android.internal.widget.remotecompose.core.operations.layout.ComponentStartOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.LayoutComponent;
+import com.android.internal.widget.remotecompose.core.operations.layout.measure.ComponentMeasure;
+import com.android.internal.widget.remotecompose.core.operations.layout.measure.MeasurePass;
+import com.android.internal.widget.remotecompose.core.operations.layout.measure.Size;
+import com.android.internal.widget.remotecompose.core.operations.layout.utils.DebugLog;
+
+import java.util.List;
+
+/**
+ * Simple Column layout implementation
+ * - also supports weight and horizontal/vertical positioning
+ */
+public class ColumnLayout extends LayoutManager implements ComponentStartOperation {
+ public static final int START = 1;
+ public static final int CENTER = 2;
+ public static final int END = 3;
+ public static final int TOP = 4;
+ public static final int BOTTOM = 5;
+ public static final int SPACE_BETWEEN = 6;
+ public static final int SPACE_EVENLY = 7;
+ public static final int SPACE_AROUND = 8;
+
+ public static final ColumnLayout.Companion COMPANION = new ColumnLayout.Companion();
+
+ int mHorizontalPositioning;
+ int mVerticalPositioning;
+ float mSpacedBy = 0f;
+
+ public ColumnLayout(Component parent, int componentId, int animationId,
+ float x, float y, float width, float height,
+ int horizontalPositioning, int verticalPositioning, float spacedBy) {
+ super(parent, componentId, animationId, x, y, width, height);
+ mHorizontalPositioning = horizontalPositioning;
+ mVerticalPositioning = verticalPositioning;
+ mSpacedBy = spacedBy;
+ }
+
+ public ColumnLayout(Component parent, int componentId, int animationId,
+ int horizontalPositioning, int verticalPositioning, float spacedBy) {
+ this(parent, componentId, animationId, 0, 0, 0, 0,
+ horizontalPositioning, verticalPositioning, spacedBy);
+ }
+
+ @Override
+ public String toString() {
+ return "COLUMN [" + mComponentId + ":" + mAnimationId + "] (" + mX + ", "
+ + mY + " - " + mWidth + " x " + mHeight + ") " + mVisibility;
+ }
+
+ protected String getSerializedName() {
+ return "COLUMN";
+ }
+
+ @Override
+ public void computeWrapSize(PaintContext context, float maxWidth, float maxHeight,
+ MeasurePass measure, Size size) {
+ DebugLog.s(() -> "COMPUTE WRAP SIZE in " + this + " (" + mComponentId + ")");
+ for (Component c : mChildrenComponents) {
+ c.measure(context, 0f, maxWidth,
+ 0f, maxHeight, measure);
+ ComponentMeasure m = measure.get(c);
+ size.setWidth(Math.max(size.getWidth(), m.getW()));
+ size.setHeight(size.getHeight() + m.getH());
+ }
+ if (!mChildrenComponents.isEmpty()) {
+ size.setHeight(size.getHeight()
+ + (mSpacedBy * (mChildrenComponents.size() - 1)));
+ }
+ DebugLog.e();
+ }
+
+ @Override
+ public void computeSize(PaintContext context, float minWidth, float maxWidth,
+ float minHeight, float maxHeight, MeasurePass measure) {
+ DebugLog.s(() -> "COMPUTE SIZE in " + this + " (" + mComponentId + ")");
+ float mh = maxHeight;
+ for (Component child : mChildrenComponents) {
+ child.measure(context, minWidth, maxWidth, minHeight, mh, measure);
+ ComponentMeasure m = measure.get(child);
+ mh -= m.getH();
+ }
+ DebugLog.e();
+ }
+
+ @Override
+ public void internalLayoutMeasure(PaintContext context,
+ MeasurePass measure) {
+ ComponentMeasure selfMeasure = measure.get(this);
+ DebugLog.s(() -> "INTERNAL LAYOUT " + this + " (" + mComponentId + ") children: "
+ + mChildrenComponents.size() + " size (" + selfMeasure.getW()
+ + " x " + selfMeasure.getH() + ")");
+ if (mChildrenComponents.isEmpty()) {
+ DebugLog.e();
+ return;
+ }
+ float selfWidth = selfMeasure.getW() - mPaddingLeft - mPaddingRight;
+ float selfHeight = selfMeasure.getH() - mPaddingTop - mPaddingBottom;
+ float childrenWidth = 0f;
+ float childrenHeight = 0f;
+
+ boolean hasWeights = false;
+ float totalWeights = 0f;
+ for (Component child : mChildrenComponents) {
+ ComponentMeasure childMeasure = measure.get(child);
+ if (child instanceof LayoutComponent
+ && ((LayoutComponent) child).getHeightModifier().hasWeight()) {
+ hasWeights = true;
+ totalWeights += ((LayoutComponent) child).getHeightModifier().getValue();
+ } else {
+ childrenHeight += childMeasure.getH();
+ }
+ }
+ if (hasWeights) {
+ float availableSpace = selfHeight - childrenHeight;
+ for (Component child : mChildrenComponents) {
+ if (child instanceof LayoutComponent
+ && ((LayoutComponent) child).getHeightModifier().hasWeight()) {
+ ComponentMeasure childMeasure = measure.get(child);
+ float weight = ((LayoutComponent) child).getHeightModifier().getValue();
+ childMeasure.setH((weight * availableSpace) / totalWeights);
+ child.measure(context, childMeasure.getW(),
+ childMeasure.getW(), childMeasure.getH(), childMeasure.getH(), measure);
+ }
+ }
+ }
+
+ childrenHeight = 0f;
+ for (Component child : mChildrenComponents) {
+ ComponentMeasure childMeasure = measure.get(child);
+ childrenWidth = Math.max(childrenWidth, childMeasure.getW());
+ childrenHeight += childMeasure.getH();
+ }
+ childrenHeight += mSpacedBy * (mChildrenComponents.size() - 1);
+
+ float tx = 0f;
+ float ty = 0f;
+
+ float verticalGap = 0f;
+ float total = 0f;
+ switch (mVerticalPositioning) {
+ case TOP:
+ ty = 0f;
+ break;
+ case CENTER:
+ ty = (selfHeight - childrenHeight) / 2f;
+ break;
+ case BOTTOM:
+ ty = selfHeight - childrenHeight;
+ break;
+ case SPACE_BETWEEN:
+ for (Component child : mChildrenComponents) {
+ ComponentMeasure childMeasure = measure.get(child);
+ total += childMeasure.getH();
+ }
+ verticalGap = (selfHeight - total) / (mChildrenComponents.size() - 1);
+ break;
+ case SPACE_EVENLY:
+ for (Component child : mChildrenComponents) {
+ ComponentMeasure childMeasure = measure.get(child);
+ total += childMeasure.getH();
+ }
+ verticalGap = (selfHeight - total) / (mChildrenComponents.size() + 1);
+ ty = verticalGap;
+ break;
+ case SPACE_AROUND:
+ for (Component child : mChildrenComponents) {
+ ComponentMeasure childMeasure = measure.get(child);
+ total += childMeasure.getH();
+ }
+ verticalGap = (selfHeight - total) / (mChildrenComponents.size());
+ ty = verticalGap / 2f;
+ break;
+ }
+ for (Component child : mChildrenComponents) {
+ ComponentMeasure childMeasure = measure.get(child);
+ switch (mHorizontalPositioning) {
+ case START:
+ tx = 0f;
+ break;
+ case CENTER:
+ tx = (selfWidth - childMeasure.getW()) / 2f;
+ break;
+ case END:
+ tx = selfWidth - childMeasure.getW();
+ break;
+ }
+ childMeasure.setX(tx);
+ childMeasure.setY(ty);
+ childMeasure.setVisibility(child.mVisibility);
+ ty += childMeasure.getH();
+ if (mVerticalPositioning == SPACE_BETWEEN
+ || mVerticalPositioning == SPACE_AROUND
+ || mVerticalPositioning == SPACE_EVENLY) {
+ ty += verticalGap;
+ }
+ ty += mSpacedBy;
+ }
+ DebugLog.e();
+ }
+
+ public static class Companion implements DocumentedCompanionOperation {
+ @Override
+ public String name() {
+ return "ColumnLayout";
+ }
+
+ @Override
+ public int id() {
+ return Operations.LAYOUT_COLUMN;
+ }
+
+ public void apply(WireBuffer buffer, int componentId, int animationId,
+ int horizontalPositioning, int verticalPositioning, float spacedBy) {
+ buffer.start(Operations.LAYOUT_COLUMN);
+ buffer.writeInt(componentId);
+ buffer.writeInt(animationId);
+ buffer.writeInt(horizontalPositioning);
+ buffer.writeInt(verticalPositioning);
+ buffer.writeFloat(spacedBy);
+ }
+
+ @Override
+ public void read(WireBuffer buffer, List<Operation> operations) {
+ int componentId = buffer.readInt();
+ int animationId = buffer.readInt();
+ int horizontalPositioning = buffer.readInt();
+ int verticalPositioning = buffer.readInt();
+ float spacedBy = buffer.readFloat();
+ operations.add(new ColumnLayout(null, componentId, animationId,
+ horizontalPositioning, verticalPositioning, spacedBy));
+ }
+
+ @Override
+ public void documentation(DocumentationBuilder doc) {
+ doc.operation("Layout Operations", id(), name())
+ .description("Column layout implementation, positioning components one"
+ + " after the other vertically.\n\n"
+ + "It supports weight and horizontal/vertical positioning.")
+ .examplesDimension(100, 400)
+ .exampleImage("Top", "layout-ColumnLayout-start-top.png")
+ .exampleImage("Center", "layout-ColumnLayout-start-center.png")
+ .exampleImage("Bottom", "layout-ColumnLayout-start-bottom.png")
+ .exampleImage("SpaceEvenly", "layout-ColumnLayout-start-space-evenly.png")
+ .exampleImage("SpaceAround", "layout-ColumnLayout-start-space-around.png")
+ .exampleImage("SpaceBetween", "layout-ColumnLayout-start-space-between.png")
+ .field(INT, "COMPONENT_ID", "unique id for this component")
+ .field(INT, "ANIMATION_ID", "id used to match components,"
+ + " for animation purposes")
+ .field(INT, "HORIZONTAL_POSITIONING", "horizontal positioning value")
+ .possibleValues("START", ColumnLayout.START)
+ .possibleValues("CENTER", ColumnLayout.CENTER)
+ .possibleValues("END", ColumnLayout.END)
+ .field(INT, "VERTICAL_POSITIONING", "vertical positioning value")
+ .possibleValues("TOP", ColumnLayout.TOP)
+ .possibleValues("CENTER", ColumnLayout.CENTER)
+ .possibleValues("BOTTOM", ColumnLayout.BOTTOM)
+ .possibleValues("SPACE_BETWEEN", ColumnLayout.SPACE_BETWEEN)
+ .possibleValues("SPACE_EVENLY", ColumnLayout.SPACE_EVENLY)
+ .possibleValues("SPACE_AROUND", ColumnLayout.SPACE_AROUND)
+ .field(FLOAT, "SPACED_BY", "Horizontal spacing between components");
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/LayoutManager.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/LayoutManager.java
new file mode 100644
index 0000000..4890683
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/LayoutManager.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout.managers;
+
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.operations.layout.Component;
+import com.android.internal.widget.remotecompose.core.operations.layout.LayoutComponent;
+import com.android.internal.widget.remotecompose.core.operations.layout.measure.ComponentMeasure;
+import com.android.internal.widget.remotecompose.core.operations.layout.measure.Measurable;
+import com.android.internal.widget.remotecompose.core.operations.layout.measure.MeasurePass;
+import com.android.internal.widget.remotecompose.core.operations.layout.measure.Size;
+
+/**
+ * Base class for layout managers -- resizable components.
+ */
+public abstract class LayoutManager extends LayoutComponent implements Measurable {
+
+ Size mCachedWrapSize = new Size(0f, 0f);
+
+ public LayoutManager(Component parent, int componentId, int animationId,
+ float x, float y, float width, float height) {
+ super(parent, componentId, animationId, x, y, width, height);
+ }
+
+ /**
+ * Implemented by subclasses to provide a layout/measure pass
+ */
+ public void internalLayoutMeasure(PaintContext context,
+ MeasurePass measure) {
+ // nothing here
+ }
+
+ /**
+ * Subclasses can implement this to provide wrap sizing
+ */
+ public void computeWrapSize(PaintContext context, float maxWidth, float maxHeight,
+ MeasurePass measure, Size size) {
+ // nothing here
+ }
+
+ /**
+ * Subclasses can implement this when not in wrap sizing
+ */
+ public void computeSize(PaintContext context, float minWidth, float maxWidth,
+ float minHeight, float maxHeight, MeasurePass measure) {
+ // nothing here
+ }
+
+ /**
+ * Base implementation of the measure resolution
+ */
+ @Override
+ public void measure(PaintContext context, float minWidth, float maxWidth,
+ float minHeight, float maxHeight, MeasurePass measure) {
+ boolean hasWrap = true;
+ float measuredWidth = Math.min(maxWidth,
+ computeModifierDefinedWidth() - mMarginLeft - mMarginRight);
+ float measuredHeight = Math.min(maxHeight,
+ computeModifierDefinedHeight() - mMarginTop - mMarginBottom);
+ float insetMaxWidth = maxWidth - mMarginLeft - mMarginRight;
+ float insetMaxHeight = maxHeight - mMarginTop - mMarginBottom;
+ if (mWidthModifier.isWrap() || mHeightModifier.isWrap()) {
+ mCachedWrapSize.setWidth(0f);
+ mCachedWrapSize.setHeight(0f);
+ computeWrapSize(context, maxWidth, maxHeight, measure, mCachedWrapSize);
+ measuredWidth = mCachedWrapSize.getWidth();
+ measuredHeight = mCachedWrapSize.getHeight();
+ } else {
+ hasWrap = false;
+ }
+ if (mWidthModifier.isFill()) {
+ measuredWidth = insetMaxWidth;
+ } else if (mWidthModifier.hasWeight()) {
+ measuredWidth = Math.max(measuredWidth, computeModifierDefinedWidth());
+ } else {
+ measuredWidth = Math.max(measuredWidth, minWidth);
+ measuredWidth = Math.min(measuredWidth, insetMaxWidth);
+ }
+ if (mHeightModifier.isFill()) {
+ measuredHeight = insetMaxHeight;
+ } else if (mHeightModifier.hasWeight()) {
+ measuredHeight = Math.max(measuredHeight, computeModifierDefinedHeight());
+ } else {
+ measuredHeight = Math.max(measuredHeight, minHeight);
+ measuredHeight = Math.min(measuredHeight, insetMaxHeight);
+ }
+ if (minWidth == maxWidth) {
+ measuredWidth = maxWidth;
+ }
+ if (minHeight == maxHeight) {
+ measuredHeight = maxHeight;
+ }
+ measuredWidth = Math.min(measuredWidth, insetMaxWidth);
+ measuredHeight = Math.min(measuredHeight, insetMaxHeight);
+ if (!hasWrap) {
+ computeSize(context, 0f, measuredWidth, 0f, measuredHeight, measure);
+ }
+ measuredWidth += mMarginLeft + mMarginRight;
+ measuredHeight += mMarginTop + mMarginBottom;
+
+ ComponentMeasure m = measure.get(this);
+ m.setW(measuredWidth);
+ m.setH(measuredHeight);
+
+ internalLayoutMeasure(context, measure);
+ }
+
+ /**
+ * basic layout of internal components
+ */
+ @Override
+ public void layout(RemoteContext context, MeasurePass measure) {
+ super.layout(context, measure);
+ ComponentMeasure self = measure.get(this);
+
+ mComponentModifiers.layout(context, self.getW(), self.getH());
+ for (Component c : mChildrenComponents) {
+ c.layout(context, measure);
+ }
+ this.mNeedsMeasure = false;
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java
new file mode 100644
index 0000000..07e2ea1
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.widget.remotecompose.core.operations.layout.managers;
+
+import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT;
+import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentedCompanionOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.Component;
+import com.android.internal.widget.remotecompose.core.operations.layout.ComponentStartOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.LayoutComponent;
+import com.android.internal.widget.remotecompose.core.operations.layout.measure.ComponentMeasure;
+import com.android.internal.widget.remotecompose.core.operations.layout.measure.MeasurePass;
+import com.android.internal.widget.remotecompose.core.operations.layout.measure.Size;
+import com.android.internal.widget.remotecompose.core.operations.layout.utils.DebugLog;
+
+import java.util.List;
+
+/**
+ * Simple Row layout implementation
+ * - also supports weight and horizontal/vertical positioning
+ */
+public class RowLayout extends LayoutManager implements ComponentStartOperation {
+ public static final int START = 1;
+ public static final int CENTER = 2;
+ public static final int END = 3;
+ public static final int TOP = 4;
+ public static final int BOTTOM = 5;
+ public static final int SPACE_BETWEEN = 6;
+ public static final int SPACE_EVENLY = 7;
+ public static final int SPACE_AROUND = 8;
+
+ public static final RowLayout.Companion COMPANION = new RowLayout.Companion();
+
+ int mHorizontalPositioning;
+ int mVerticalPositioning;
+ float mSpacedBy = 0f;
+
+ public RowLayout(Component parent, int componentId, int animationId,
+ float x, float y, float width, float height,
+ int horizontalPositioning, int verticalPositioning, float spacedBy) {
+ super(parent, componentId, animationId, x, y, width, height);
+ mHorizontalPositioning = horizontalPositioning;
+ mVerticalPositioning = verticalPositioning;
+ mSpacedBy = spacedBy;
+ }
+
+ public RowLayout(Component parent, int componentId, int animationId,
+ int horizontalPositioning, int verticalPositioning, float spacedBy) {
+ this(parent, componentId, animationId, 0, 0, 0, 0,
+ horizontalPositioning, verticalPositioning, spacedBy);
+ }
+ @Override
+ public String toString() {
+ return "ROW [" + mComponentId + ":" + mAnimationId + "] (" + mX + ", "
+ + mY + " - " + mWidth + " x " + mHeight + ") " + mVisibility;
+ }
+
+ protected String getSerializedName() {
+ return "ROW";
+ }
+
+ @Override
+ public void computeWrapSize(PaintContext context, float maxWidth, float maxHeight,
+ MeasurePass measure, Size size) {
+ DebugLog.s(() -> "COMPUTE WRAP SIZE in " + this + " (" + mComponentId + ")");
+ for (Component c : mChildrenComponents) {
+ c.measure(context, 0f, maxWidth, 0f, maxHeight, measure);
+ ComponentMeasure m = measure.get(c);
+ size.setWidth(size.getWidth() + m.getW());
+ size.setHeight(Math.max(size.getHeight(), m.getH()));
+ }
+ if (!mChildrenComponents.isEmpty()) {
+ size.setWidth(size.getWidth()
+ + (mSpacedBy * (mChildrenComponents.size() - 1)));
+ }
+ DebugLog.e();
+ }
+
+ @Override
+ public void computeSize(PaintContext context, float minWidth, float maxWidth,
+ float minHeight, float maxHeight, MeasurePass measure) {
+ DebugLog.s(() -> "COMPUTE SIZE in " + this + " (" + mComponentId + ")");
+ float mw = maxWidth;
+ for (Component child : mChildrenComponents) {
+ child.measure(context, minWidth, mw, minHeight, maxHeight, measure);
+ ComponentMeasure m = measure.get(child);
+ mw -= m.getW();
+ }
+ DebugLog.e();
+ }
+
+ @Override
+ public void internalLayoutMeasure(PaintContext context,
+ MeasurePass measure) {
+ ComponentMeasure selfMeasure = measure.get(this);
+ DebugLog.s(() -> "INTERNAL LAYOUT " + this + " (" + mComponentId + ") children: "
+ + mChildrenComponents.size() + " size (" + selfMeasure.getW()
+ + " x " + selfMeasure.getH() + ")");
+ if (mChildrenComponents.isEmpty()) {
+ DebugLog.e();
+ return;
+ }
+ float selfWidth = selfMeasure.getW() - mPaddingLeft - mPaddingRight;
+ float selfHeight = selfMeasure.getH() - mPaddingTop - mPaddingBottom;
+ float childrenWidth = 0f;
+ float childrenHeight = 0f;
+
+ boolean hasWeights = false;
+ float totalWeights = 0f;
+ for (Component child : mChildrenComponents) {
+ ComponentMeasure childMeasure = measure.get(child);
+ if (child instanceof LayoutComponent
+ && ((LayoutComponent) child).getWidthModifier().hasWeight()) {
+ hasWeights = true;
+ totalWeights += ((LayoutComponent) child).getWidthModifier().getValue();
+ } else {
+ childrenWidth += childMeasure.getW();
+ }
+ }
+
+ // TODO: need to move the weight measuring in the measure function,
+ // currently we'll measure unnecessarily
+ if (hasWeights) {
+ float availableSpace = selfWidth - childrenWidth;
+ for (Component child : mChildrenComponents) {
+ if (child instanceof LayoutComponent
+ && ((LayoutComponent) child).getWidthModifier().hasWeight()) {
+ ComponentMeasure childMeasure = measure.get(child);
+ float weight = ((LayoutComponent) child).getWidthModifier().getValue();
+ childMeasure.setW((weight * availableSpace) / totalWeights);
+ child.measure(context, childMeasure.getW(),
+ childMeasure.getW(), childMeasure.getH(), childMeasure.getH(), measure);
+ }
+ }
+ }
+
+ childrenWidth = 0f;
+ for (Component child : mChildrenComponents) {
+ ComponentMeasure childMeasure = measure.get(child);
+ childrenWidth += childMeasure.getW();
+ childrenHeight = Math.max(childrenHeight, childMeasure.getH());
+ }
+ childrenWidth += mSpacedBy * (mChildrenComponents.size() - 1);
+
+ float tx = 0f;
+ float ty = 0f;
+
+ float horizontalGap = 0f;
+ float total = 0f;
+
+ switch (mHorizontalPositioning) {
+ case START:
+ tx = 0f;
+ break;
+ case END:
+ tx = selfWidth - childrenWidth;
+ break;
+ case CENTER:
+ tx = (selfWidth - childrenWidth) / 2f;
+ break;
+ case SPACE_BETWEEN:
+ for (Component child : mChildrenComponents) {
+ ComponentMeasure childMeasure = measure.get(child);
+ total += childMeasure.getW();
+ }
+ horizontalGap = (selfWidth - total) / (mChildrenComponents.size() - 1);
+ break;
+ case SPACE_EVENLY:
+ for (Component child : mChildrenComponents) {
+ ComponentMeasure childMeasure = measure.get(child);
+ total += childMeasure.getW();
+ }
+ horizontalGap = (selfWidth - total) / (mChildrenComponents.size() + 1);
+ tx = horizontalGap;
+ break;
+ case SPACE_AROUND:
+ for (Component child : mChildrenComponents) {
+ ComponentMeasure childMeasure = measure.get(child);
+ total += childMeasure.getW();
+ }
+ horizontalGap = (selfWidth - total) / (mChildrenComponents.size());
+ tx = horizontalGap / 2f;
+ break;
+ }
+
+ for (Component child : mChildrenComponents) {
+ ComponentMeasure childMeasure = measure.get(child);
+ switch (mVerticalPositioning) {
+ case TOP:
+ ty = 0f;
+ break;
+ case CENTER:
+ ty = (selfHeight - childMeasure.getH()) / 2f;
+ break;
+ case BOTTOM:
+ ty = selfHeight - childMeasure.getH();
+ break;
+ }
+ childMeasure.setX(tx);
+ childMeasure.setY(ty);
+ childMeasure.setVisibility(child.mVisibility);
+ tx += childMeasure.getW();
+ if (mHorizontalPositioning == SPACE_BETWEEN
+ || mHorizontalPositioning == SPACE_AROUND
+ || mHorizontalPositioning == SPACE_EVENLY) {
+ tx += horizontalGap;
+ }
+ tx += mSpacedBy;
+ }
+ DebugLog.e();
+ }
+
+ public static class Companion implements DocumentedCompanionOperation {
+ @Override
+ public String name() {
+ return "RowLayout";
+ }
+
+ @Override
+ public int id() {
+ return Operations.LAYOUT_ROW;
+ }
+
+ public void apply(WireBuffer buffer, int componentId, int animationId,
+ int horizontalPositioning, int verticalPositioning, float spacedBy) {
+ buffer.start(Operations.LAYOUT_ROW);
+ buffer.writeInt(componentId);
+ buffer.writeInt(animationId);
+ buffer.writeInt(horizontalPositioning);
+ buffer.writeInt(verticalPositioning);
+ buffer.writeFloat(spacedBy);
+ }
+
+ @Override
+ public void read(WireBuffer buffer, List<Operation> operations) {
+ int componentId = buffer.readInt();
+ int animationId = buffer.readInt();
+ int horizontalPositioning = buffer.readInt();
+ int verticalPositioning = buffer.readInt();
+ float spacedBy = buffer.readFloat();
+ operations.add(new RowLayout(null, componentId, animationId,
+ horizontalPositioning, verticalPositioning, spacedBy));
+ }
+
+ @Override
+ public void documentation(DocumentationBuilder doc) {
+ doc.operation("Layout Operations", id(), name())
+ .description("Row layout implementation, positioning components one"
+ + " after the other horizontally.\n\n"
+ + "It supports weight and horizontal/vertical positioning.")
+ .examplesDimension(400, 100)
+ .exampleImage("Start", "layout-RowLayout-start-top.png")
+ .exampleImage("Center", "layout-RowLayout-center-top.png")
+ .exampleImage("End", "layout-RowLayout-end-top.png")
+ .exampleImage("SpaceEvenly", "layout-RowLayout-space-evenly-top.png")
+ .exampleImage("SpaceAround", "layout-RowLayout-space-around-top.png")
+ .exampleImage("SpaceBetween", "layout-RowLayout-space-between-top.png")
+ .field(INT, "COMPONENT_ID", "unique id for this component")
+ .field(INT, "ANIMATION_ID", "id used to match components,"
+ + " for animation purposes")
+ .field(INT, "HORIZONTAL_POSITIONING", "horizontal positioning value")
+ .possibleValues("START", RowLayout.START)
+ .possibleValues("CENTER", RowLayout.CENTER)
+ .possibleValues("END", RowLayout.END)
+ .possibleValues("SPACE_BETWEEN", RowLayout.SPACE_BETWEEN)
+ .possibleValues("SPACE_EVENLY", RowLayout.SPACE_EVENLY)
+ .possibleValues("SPACE_AROUND", RowLayout.SPACE_AROUND)
+ .field(INT, "VERTICAL_POSITIONING", "vertical positioning value")
+ .possibleValues("TOP", RowLayout.TOP)
+ .possibleValues("CENTER", RowLayout.CENTER)
+ .possibleValues("BOTTOM", RowLayout.BOTTOM)
+ .field(FLOAT, "SPACED_BY", "Horizontal spacing between components");
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/ComponentMeasure.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/ComponentMeasure.java
new file mode 100644
index 0000000..8dc10d5
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/ComponentMeasure.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget.remotecompose.core.operations.layout.measure;
+import com.android.internal.widget.remotecompose.core.operations.layout.Component;
+
+/**
+ * Encapsulate the result of a measure pass for a component
+ */
+public class ComponentMeasure {
+ int mId = -1;
+ float mX;
+ float mY;
+ float mW;
+ float mH;
+ Component.Visibility mVisibility = Component.Visibility.VISIBLE;
+
+ public void setX(float value) {
+ mX = value;
+ }
+ public void setY(float value) {
+ mY = value;
+ }
+ public void setW(float value) {
+ mW = value;
+ }
+ public void setH(float value) {
+ mH = value;
+ }
+ public float getX() {
+ return mX;
+ }
+ public float getY() {
+ return mY;
+ }
+ public float getW() {
+ return mW;
+ }
+ public float getH() {
+ return mH;
+ }
+
+ public Component.Visibility getVisibility() {
+ return mVisibility;
+ }
+
+ public void setVisibility(Component.Visibility visibility) {
+ mVisibility = visibility;
+ }
+
+ public ComponentMeasure(int id, float x, float y, float w, float h,
+ Component.Visibility visibility) {
+ this.mId = id;
+ this.mX = x;
+ this.mY = y;
+ this.mW = w;
+ this.mH = h;
+ this.mVisibility = visibility;
+ }
+
+ public ComponentMeasure(int id, float x, float y, float w, float h) {
+ this(id, x, y, w, h, Component.Visibility.VISIBLE);
+ }
+
+ public ComponentMeasure(Component component) {
+ this(component.getComponentId(), component.getX(), component.getY(),
+ component.getWidth(), component.getHeight(),
+ component.mVisibility);
+ }
+
+ public void copyFrom(ComponentMeasure m) {
+ mX = m.mX;
+ mY = m.mY;
+ mW = m.mW;
+ mH = m.mH;
+ mVisibility = m.mVisibility;
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/Measurable.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/Measurable.java
new file mode 100644
index 0000000..d167d9b
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/Measurable.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget.remotecompose.core.operations.layout.measure;
+
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+
+/**
+ * Interface describing the measure/layout contract for components
+ */
+public interface Measurable {
+
+ /**
+ * Measure a component and store the result of the measure in the provided MeasurePass.
+ * This does not apply the measure to the component.
+ */
+ void measure(PaintContext context, float minWidth, float maxWidth,
+ float minHeight, float maxHeight, MeasurePass measure);
+
+ /**
+ * Apply a given measure to the component
+ */
+ void layout(RemoteContext context, MeasurePass measure);
+
+ /**
+ * Return true if the component needs to be remeasured
+ * @return true if need to remeasured, false otherwise
+ */
+ boolean needsMeasure();
+
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/MeasurePass.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/MeasurePass.java
new file mode 100644
index 0000000..6801deb
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/MeasurePass.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout.measure;
+
+import com.android.internal.widget.remotecompose.core.operations.layout.Component;
+
+import java.util.HashMap;
+
+/**
+ * Represents the result of a measure pass on the entire hierarchy
+ * TODO: optimize to use a flat array vs the current hashmap
+ */
+public class MeasurePass {
+ HashMap<Integer, ComponentMeasure> mList = new HashMap<>();
+
+ public void clear() {
+ mList.clear();
+ }
+
+ public void add(ComponentMeasure measure) throws Exception {
+ if (measure.mId == -1) {
+ throw new Exception("Component has no id!");
+ }
+ mList.put(measure.mId, measure);
+ }
+
+ public boolean contains(int id) {
+ return mList.containsKey(id);
+ }
+
+ public ComponentMeasure get(Component c) {
+ if (!mList.containsKey(c.getComponentId())) {
+ ComponentMeasure measure = new ComponentMeasure(c.getComponentId(),
+ c.getX(), c.getY(), c.getWidth(), c.getHeight());
+ mList.put(c.getComponentId(), measure);
+ return measure;
+ }
+ return mList.get(c.getComponentId());
+ }
+
+ public ComponentMeasure get(int id) {
+ if (!mList.containsKey(id)) {
+ ComponentMeasure measure = new ComponentMeasure(id,
+ 0f, 0f, 0f, 0f, Component.Visibility.GONE);
+ mList.put(id, measure);
+ return measure;
+ }
+ return mList.get(id);
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/Size.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/Size.java
new file mode 100644
index 0000000..b11d8e8
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/Size.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout.measure;
+
+/**
+ * Basic data class representing a component size, used during layout computations.
+ */
+public class Size {
+ float mWidth;
+ float mHeight;
+ public Size(float width, float height) {
+ this.mWidth = width;
+ this.mHeight = height;
+ }
+
+ public void setWidth(float value) {
+ mWidth = value;
+ }
+
+ public void setHeight(float value) {
+ mHeight = value;
+ }
+
+ public float getWidth() {
+ return mWidth;
+ }
+
+ public float getHeight() {
+ return mHeight;
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java
new file mode 100644
index 0000000..6f48aee
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout.modifiers;
+
+import com.android.internal.widget.remotecompose.core.CompanionOperation;
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.operations.paint.PaintBundle;
+import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
+
+import java.util.List;
+
+/**
+ * Component size-aware background draw
+ */
+public class BackgroundModifierOperation extends DecoratorModifierOperation {
+
+ public static final BackgroundModifierOperation.Companion COMPANION =
+ new BackgroundModifierOperation.Companion();
+
+ float mX;
+ float mY;
+ float mWidth;
+ float mHeight;
+ float mR;
+ float mG;
+ float mB;
+ float mA;
+ int mShapeType = ShapeType.RECTANGLE;
+
+ public PaintBundle mPaint = new PaintBundle();
+
+ public BackgroundModifierOperation(float x, float y, float width, float height,
+ float r, float g, float b, float a,
+ int shapeType) {
+ this.mX = x;
+ this.mY = y;
+ this.mWidth = width;
+ this.mHeight = height;
+ this.mR = r;
+ this.mG = g;
+ this.mB = b;
+ this.mA = a;
+ this.mShapeType = shapeType;
+ }
+
+ @Override
+ public void write(WireBuffer buffer) {
+ COMPANION.apply(buffer, mX, mY, mWidth, mHeight, mR, mG, mB, mA, mShapeType);
+ }
+
+ @Override
+ public void serializeToString(int indent, StringSerializer serializer) {
+ serializer.append(indent, "BACKGROUND = [" + mX + ", "
+ + mY + ", " + mWidth + ", " + mHeight
+ + "] color [" + mR + ", " + mG + ", " + mB + ", " + mA
+ + "] shape [" + mShapeType + "]");
+ }
+
+ @Override
+ public void layout(RemoteContext context, float width, float height) {
+ this.mWidth = width;
+ this.mHeight = height;
+ }
+
+ @Override
+ public String toString() {
+ return "BackgroundModifierOperation(" + mWidth + " x " + mHeight + ")";
+ }
+
+ public static class Companion implements CompanionOperation {
+
+
+ @Override
+ public String name() {
+ return "OrigamiBackground";
+ }
+
+ @Override
+ public int id() {
+ return Operations.MODIFIER_BACKGROUND;
+ }
+
+ public void apply(WireBuffer buffer, float x, float y, float width, float height,
+ float r, float g, float b, float a, int shapeType) {
+ buffer.start(Operations.MODIFIER_BACKGROUND);
+ buffer.writeFloat(x);
+ buffer.writeFloat(y);
+ buffer.writeFloat(width);
+ buffer.writeFloat(height);
+ buffer.writeFloat(r);
+ buffer.writeFloat(g);
+ buffer.writeFloat(b);
+ buffer.writeFloat(a);
+ // shape type
+ buffer.writeInt(shapeType);
+ }
+
+ @Override
+ public void read(WireBuffer buffer, List<Operation> operations) {
+ float x = buffer.readFloat();
+ float y = buffer.readFloat();
+ float width = buffer.readFloat();
+ float height = buffer.readFloat();
+ float r = buffer.readFloat();
+ float g = buffer.readFloat();
+ float b = buffer.readFloat();
+ float a = buffer.readFloat();
+ // shape type
+ int shapeType = buffer.readInt();
+ operations.add(new BackgroundModifierOperation(x, y, width, height,
+ r, g, b, a, shapeType));
+ }
+ }
+
+ @Override
+ public void paint(PaintContext context) {
+ context.savePaint();
+ mPaint.reset();
+ mPaint.setColor(mR, mG, mB, mA);
+ context.applyPaint(mPaint);
+ if (mShapeType == ShapeType.RECTANGLE) {
+ context.drawRect(0f, 0f, mWidth, mHeight);
+ } else if (mShapeType == ShapeType.CIRCLE) {
+ context.drawCircle(mWidth / 2f, mHeight / 2f,
+ Math.min(mWidth, mHeight) / 2f);
+ }
+ context.restorePaint();
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java
new file mode 100644
index 0000000..0b9c01b
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.widget.remotecompose.core.operations.layout.modifiers;
+
+import com.android.internal.widget.remotecompose.core.CompanionOperation;
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.operations.paint.PaintBundle;
+import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
+
+import java.util.List;
+
+/**
+ * Component size-aware border draw
+ */
+public class BorderModifierOperation extends DecoratorModifierOperation {
+
+ public static final BorderModifierOperation.Companion COMPANION =
+ new BorderModifierOperation.Companion();
+
+ float mX;
+ float mY;
+ float mWidth;
+ float mHeight;
+ float mBorderWidth;
+ float mRoundedCorner;
+ float mR;
+ float mG;
+ float mB;
+ float mA;
+ int mShapeType = ShapeType.RECTANGLE;
+
+ public PaintBundle paint = new PaintBundle();
+
+ public BorderModifierOperation(float x, float y, float width, float height,
+ float borderWidth, float roundedCorner,
+ float r, float g, float b, float a, int shapeType) {
+ this.mX = x;
+ this.mY = y;
+ this.mWidth = width;
+ this.mHeight = height;
+ this.mBorderWidth = borderWidth;
+ this.mRoundedCorner = roundedCorner;
+ this.mR = r;
+ this.mG = g;
+ this.mB = b;
+ this.mA = a;
+ this.mShapeType = shapeType;
+ }
+
+ @Override
+ public void serializeToString(int indent, StringSerializer serializer) {
+ serializer.append(indent, "BORDER = [" + mX + ", " + mY + ", "
+ + mWidth + ", " + mHeight + "] "
+ + "color [" + mR + ", " + mG + ", " + mB + ", " + mA + "] "
+ + "border [" + mBorderWidth + ", " + mRoundedCorner + "] "
+ + "shape [" + mShapeType + "]");
+ }
+
+ @Override
+ public void write(WireBuffer buffer) {
+ COMPANION.apply(buffer, mX, mY, mWidth, mHeight, mBorderWidth, mRoundedCorner,
+ mR, mG, mB, mA, mShapeType);
+ }
+
+ @Override
+ public void layout(RemoteContext context, float width, float height) {
+ this.mWidth = width;
+ this.mHeight = height;
+ }
+
+ @Override
+ public String toString() {
+ return "BorderModifierOperation(" + mX + "," + mY + " - " + mWidth + " x " + mHeight + ") "
+ + "borderWidth(" + mBorderWidth + ") "
+ + "color(" + mR + "," + mG + "," + mB + "," + mA + ")";
+ }
+
+ public static class Companion implements CompanionOperation {
+
+ @Override
+ public String name() {
+ return "BorderModifier";
+ }
+
+ @Override
+ public int id() {
+ return Operations.MODIFIER_BORDER;
+ }
+
+ public void apply(WireBuffer buffer, float x, float y, float width, float height,
+ float borderWidth, float roundedCorner,
+ float r, float g, float b, float a,
+ int shapeType) {
+ buffer.start(Operations.MODIFIER_BORDER);
+ buffer.writeFloat(x);
+ buffer.writeFloat(y);
+ buffer.writeFloat(width);
+ buffer.writeFloat(height);
+ buffer.writeFloat(borderWidth);
+ buffer.writeFloat(roundedCorner);
+ buffer.writeFloat(r);
+ buffer.writeFloat(g);
+ buffer.writeFloat(b);
+ buffer.writeFloat(a);
+ // shape type
+ buffer.writeInt(shapeType);
+ }
+
+ @Override
+ public void read(WireBuffer buffer, List<Operation> operations) {
+ float x = buffer.readFloat();
+ float y = buffer.readFloat();
+ float width = buffer.readFloat();
+ float height = buffer.readFloat();
+ float bw = buffer.readFloat();
+ float rc = buffer.readFloat();
+ float r = buffer.readFloat();
+ float g = buffer.readFloat();
+ float b = buffer.readFloat();
+ float a = buffer.readFloat();
+ // shape type
+ int shapeType = buffer.readInt();
+ operations.add(new BorderModifierOperation(x, y, width, height, bw,
+ rc, r, g, b, a, shapeType));
+ }
+ }
+
+ @Override
+ public void paint(PaintContext context) {
+ context.savePaint();
+ paint.reset();
+ paint.setColor(mR, mG, mB, mA);
+ paint.setStrokeWidth(mBorderWidth);
+ paint.setStyle(PaintBundle.STYLE_STROKE);
+ context.applyPaint(paint);
+ if (mShapeType == ShapeType.RECTANGLE) {
+ context.drawRect(0f, 0f, mWidth, mHeight);
+ } else {
+ float size = mRoundedCorner;
+ if (mShapeType == ShapeType.CIRCLE) {
+ size = Math.min(mWidth, mHeight) / 2f;
+ }
+ context.drawRoundRect(0f, 0f, mWidth, mHeight, size, size);
+ }
+ context.restorePaint();
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java
new file mode 100644
index 0000000..30357af
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout.modifiers;
+
+import com.android.internal.widget.remotecompose.core.CompanionOperation;
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
+
+import java.util.List;
+
+/**
+ * Support modifier clip with a rectangle
+ */
+public class ClipRectModifierOperation extends DecoratorModifierOperation {
+
+ public static final ClipRectModifierOperation.Companion COMPANION =
+ new ClipRectModifierOperation.Companion();
+
+ float mWidth;
+ float mHeight;
+
+
+ @Override
+ public void paint(PaintContext context) {
+ context.clipRect(0f, 0f, mWidth, mHeight);
+ }
+
+ @Override
+ public void layout(RemoteContext context, float width, float height) {
+ this.mWidth = width;
+ this.mHeight = height;
+ }
+
+ @Override
+ public void onClick(float x, float y) {
+ // nothing
+ }
+
+ @Override
+ public void serializeToString(int indent, StringSerializer serializer) {
+ serializer.append(
+ indent, "CLIP_RECT = [" + mWidth + ", " + mHeight + "]");
+ }
+
+ @Override
+ public void write(WireBuffer buffer) {
+ COMPANION.apply(buffer);
+ }
+
+ public static class Companion implements CompanionOperation {
+
+ @Override
+ public String name() {
+ return "ClipRectModifier";
+ }
+
+ @Override
+ public int id() {
+ return Operations.MODIFIER_CLIP_RECT;
+ }
+
+ public void apply(WireBuffer buffer) {
+ buffer.start(Operations.MODIFIER_CLIP_RECT);
+ }
+
+ @Override
+ public void read(WireBuffer buffer, List<Operation> operations) {
+ operations.add(new ClipRectModifierOperation());
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentModifiers.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentModifiers.java
new file mode 100644
index 0000000..2ef0b9d
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentModifiers.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout.modifiers;
+
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.PaintOperation;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.operations.MatrixRestore;
+import com.android.internal.widget.remotecompose.core.operations.MatrixSave;
+import com.android.internal.widget.remotecompose.core.operations.layout.DecoratorComponent;
+import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
+
+import java.util.ArrayList;
+
+/**
+ * Maintain a list of modifiers
+ */
+public class ComponentModifiers extends PaintOperation implements DecoratorComponent {
+ ArrayList<ModifierOperation> mList = new ArrayList<>();
+
+ public ArrayList<ModifierOperation> getList() {
+ return mList;
+ }
+
+ @Override
+ public void write(WireBuffer buffer) {
+ // nothing
+ }
+
+ public void serializeToString(int indent, StringSerializer serializer) {
+ serializer.append(indent, "MODIFIERS");
+ for (ModifierOperation m : mList) {
+ m.serializeToString(indent + 1, serializer);
+ }
+ }
+
+ public void add(ModifierOperation operation) {
+ mList.add(operation);
+ }
+
+ public int size() {
+ return mList.size();
+ }
+
+ @Override
+ public void paint(PaintContext context) {
+ float tx = 0f;
+ float ty = 0f;
+ for (ModifierOperation op : mList) {
+ if (op instanceof PaddingModifierOperation) {
+ PaddingModifierOperation pop = (PaddingModifierOperation) op;
+ context.translate(pop.getLeft(), pop.getTop());
+ tx += pop.getLeft();
+ ty += pop.getTop();
+ }
+ if (op instanceof MatrixSave || op instanceof MatrixRestore) {
+ continue;
+ }
+ if (op instanceof PaintOperation) {
+ ((PaintOperation) op).paint(context);
+ }
+ }
+ // Back out the translates created by paddings
+ // TODO: we should be able to get rid of this when drawing the content of a component
+ context.translate(-tx, -ty);
+ }
+
+ @Override
+ public void layout(RemoteContext context, float width, float height) {
+ float w = width;
+ float h = height;
+ for (ModifierOperation op : mList) {
+ if (op instanceof PaddingModifierOperation) {
+ PaddingModifierOperation pop = (PaddingModifierOperation) op;
+ w -= pop.getLeft() + pop.getRight();
+ h -= pop.getTop() + pop.getBottom();
+ }
+ if (op instanceof DecoratorComponent) {
+ ((DecoratorComponent) op).layout(context, w, h);
+ }
+ }
+ }
+
+ public void addAll(ArrayList<ModifierOperation> operations) {
+ mList.addAll(operations);
+ }
+
+ public void onClick(float x, float y) {
+ for (ModifierOperation op : mList) {
+ if (op instanceof DecoratorComponent) {
+ ((DecoratorComponent) op).onClick(x, y);
+ }
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DecoratorModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DecoratorModifierOperation.java
new file mode 100644
index 0000000..bf9b27b
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DecoratorModifierOperation.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout.modifiers;
+
+import com.android.internal.widget.remotecompose.core.PaintOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.DecoratorComponent;
+
+/**
+ * Represents a decorator modifier (lightweight component), ie a modifier
+ * that impacts the visual output (background, border...)
+ */
+public abstract class DecoratorModifierOperation extends PaintOperation
+ implements ModifierOperation, DecoratorComponent {
+
+ @Override
+ public void onClick(float x, float y) {
+ // nothing
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionModifierOperation.java
new file mode 100644
index 0000000..04e9431
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionModifierOperation.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout.modifiers;
+
+import com.android.internal.widget.remotecompose.core.CompanionOperation;
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
+
+import java.util.List;
+
+/**
+ * Base class for dimension modifiers
+ */
+public class DimensionModifierOperation implements ModifierOperation {
+
+ public static final DimensionModifierOperation.Companion COMPANION =
+ new DimensionModifierOperation.Companion(0, "DIMENSION");
+
+ public enum Type {
+ EXACT, FILL, WRAP, WEIGHT, INTRINSIC_MIN, INTRINSIC_MAX;
+
+ static Type fromInt(int value) {
+ switch (value) {
+ case 0: return EXACT;
+ case 1: return FILL;
+ case 2: return WRAP;
+ case 3: return WEIGHT;
+ case 4: return INTRINSIC_MIN;
+ case 5: return INTRINSIC_MAX;
+ }
+ return EXACT;
+ }
+ }
+
+ Type mType = Type.EXACT;
+ float mValue = Float.NaN;
+
+ public DimensionModifierOperation(Type type, float value) {
+ mType = type;
+ mValue = value;
+ }
+
+ public DimensionModifierOperation(Type type) {
+ this(type, Float.NaN);
+ }
+
+ public DimensionModifierOperation(float value) {
+ this(Type.EXACT, value);
+ }
+
+
+ public boolean hasWeight() {
+ return mType == Type.WEIGHT;
+ }
+
+ public boolean isWrap() {
+ return mType == Type.WRAP;
+ }
+
+ public boolean isFill() {
+ return mType == Type.FILL;
+ }
+
+ public Type getType() {
+ return mType;
+ }
+
+ public float getValue() {
+ return mValue;
+ }
+
+ public void setValue(float value) {
+ this.mValue = value;
+ }
+
+ @Override
+ public void write(WireBuffer buffer) {
+ COMPANION.apply(buffer, mType.ordinal(), mValue);
+ }
+
+ public String serializedName() {
+ return "DIMENSION";
+ }
+
+ @Override
+ public void serializeToString(int indent, StringSerializer serializer) {
+ if (mType == Type.EXACT) {
+ serializer.append(indent, serializedName() + " = " + mValue);
+ }
+ }
+
+ @Override
+ public void apply(RemoteContext context) {
+ }
+
+ @Override
+ public String deepToString(String indent) {
+ return (indent != null ? indent : "") + toString();
+ }
+
+ @Override
+ public String toString() {
+ return "DimensionModifierOperation(" + mValue + ")";
+ }
+
+ public static class Companion implements CompanionOperation {
+
+ int mOperation;
+ String mName;
+
+ public Companion(int operation, String name) {
+ mOperation = operation;
+ mName = name;
+ }
+
+ @Override
+ public String name() {
+ return mName;
+ }
+
+ @Override
+ public int id() {
+ return mOperation;
+ }
+
+ public void apply(WireBuffer buffer, int type, float value) {
+ buffer.start(mOperation);
+ buffer.writeInt(type);
+ buffer.writeFloat(value);
+ }
+
+ public Operation construct(Type type, float value) {
+ return null;
+ }
+
+ @Override
+ public void read(WireBuffer buffer, List<Operation> operations) {
+ Type type = Type.fromInt(buffer.readInt());
+ float value = buffer.readFloat();
+ Operation op = construct(type, value);
+ operations.add(op);
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java
new file mode 100644
index 0000000..81173c3
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout.modifiers;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+
+/**
+ * Set the height dimension on a component
+ */
+public class HeightModifierOperation extends DimensionModifierOperation {
+
+ public static final DimensionModifierOperation.Companion COMPANION =
+ new DimensionModifierOperation.Companion(Operations.MODIFIER_HEIGHT, "WIDTH") {
+ @Override
+ public Operation construct(DimensionModifierOperation.Type type, float value) {
+ return new HeightModifierOperation(type, value);
+ }
+ };
+
+ public HeightModifierOperation(Type type, float value) {
+ super(type, value);
+ }
+
+ public HeightModifierOperation(Type type) {
+ super(type);
+ }
+
+ public HeightModifierOperation(float value) {
+ super(value);
+ }
+
+ @Override
+ public String toString() {
+ return "Height(" + mValue + ")";
+ }
+
+ @Override
+ public String serializedName() {
+ return "HEIGHT";
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ModifierOperation.java
similarity index 60%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
copy to core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ModifierOperation.java
index 1f04a44..5299719 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ModifierOperation.java
@@ -13,13 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.internal.widget.remotecompose.core.operations.layout.modifiers;
-package com.android.systemui.activatable
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.TestScope
-
-/** Activates [activatable] for the duration of the test. */
-fun Activatable.activateIn(testScope: TestScope) {
- testScope.backgroundScope.launch { activate() }
+/**
+ * Represents a modifier
+ */
+public interface ModifierOperation extends Operation {
+ void serializeToString(int indent, StringSerializer serializer);
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java
new file mode 100644
index 0000000..5ea6a97
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout.modifiers;
+
+import com.android.internal.widget.remotecompose.core.CompanionOperation;
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
+
+import java.util.List;
+
+/**
+ * Represents a padding modifier.
+ * Padding modifiers can be chained and will impact following modifiers.
+ */
+public class PaddingModifierOperation implements ModifierOperation {
+
+ public static final PaddingModifierOperation.Companion COMPANION =
+ new PaddingModifierOperation.Companion();
+
+ float mLeft;
+ float mTop;
+ float mRight;
+ float mBottom;
+
+ public PaddingModifierOperation(float left, float top, float right, float bottom) {
+ this.mLeft = left;
+ this.mTop = top;
+ this.mRight = right;
+ this.mBottom = bottom;
+ }
+
+ public float getLeft() {
+ return mLeft;
+ }
+
+ public float getTop() {
+ return mTop;
+ }
+
+ public float getRight() {
+ return mRight;
+ }
+
+ public float getBottom() {
+ return mBottom;
+ }
+
+ public void setLeft(float left) {
+ this.mLeft = left;
+ }
+
+ public void setTop(float top) {
+ this.mTop = top;
+ }
+
+ public void setRight(float right) {
+ this.mRight = right;
+ }
+
+ public void setBottom(float bottom) {
+ this.mBottom = bottom;
+ }
+
+ @Override
+ public void write(WireBuffer buffer) {
+ COMPANION.apply(buffer, mLeft, mTop, mRight, mBottom);
+ }
+
+ @Override
+ public void serializeToString(int indent, StringSerializer serializer) {
+ serializer.append(indent, "PADDING = [" + mLeft + ", " + mTop + ", "
+ + mRight + ", " + mBottom + "]");
+ }
+
+ @Override
+ public void apply(RemoteContext context) {
+ }
+
+ @Override
+ public String deepToString(String indent) {
+ return (indent != null ? indent : "") + toString();
+ }
+
+ @Override
+ public String toString() {
+ return "PaddingModifierOperation(" + mLeft + ", " + mTop
+ + ", " + mRight + ", " + mBottom + ")";
+ }
+
+ public static class Companion implements CompanionOperation {
+ @Override
+ public String name() {
+ return "PaddingModifierOperation";
+ }
+
+ @Override
+ public int id() {
+ return Operations.MODIFIER_PADDING;
+ }
+
+ public void apply(WireBuffer buffer,
+ float left, float top, float right, float bottom) {
+ buffer.start(Operations.MODIFIER_PADDING);
+ buffer.writeFloat(left);
+ buffer.writeFloat(top);
+ buffer.writeFloat(right);
+ buffer.writeFloat(bottom);
+ }
+
+ @Override
+ public void read(WireBuffer buffer, List<Operation> operations) {
+ float left = buffer.readFloat();
+ float top = buffer.readFloat();
+ float right = buffer.readFloat();
+ float bottom = buffer.readFloat();
+ operations.add(new PaddingModifierOperation(left, top, right, bottom));
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RoundedClipRectModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RoundedClipRectModifierOperation.java
new file mode 100644
index 0000000..9c57c6a
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RoundedClipRectModifierOperation.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout.modifiers;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.operations.DrawBase4;
+import com.android.internal.widget.remotecompose.core.operations.layout.DecoratorComponent;
+import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
+
+/**
+ * Support clip with a rectangle
+ */
+public class RoundedClipRectModifierOperation extends DrawBase4
+ implements ModifierOperation, DecoratorComponent {
+
+ public static final Companion COMPANION =
+ new Companion(Operations.MODIFIER_ROUNDED_CLIP_RECT) {
+ @Override
+ public Operation construct(float x1,
+ float y1,
+ float x2,
+ float y2) {
+ return new RoundedClipRectModifierOperation(x1, y1, x2, y2);
+ }
+ };
+ float mWidth;
+ float mHeight;
+
+
+ public RoundedClipRectModifierOperation(
+ float topStart,
+ float topEnd,
+ float bottomStart,
+ float bottomEnd) {
+ super(topStart, topEnd, bottomStart, bottomEnd);
+ mName = "ModifierRoundedClipRect";
+ }
+
+ @Override
+ public void paint(PaintContext context) {
+ context.roundedClipRect(mWidth, mHeight, mX1, mY1, mX2, mY2);
+ }
+
+ @Override
+ public void layout(RemoteContext context, float width, float height) {
+ this.mWidth = width;
+ this.mHeight = height;
+ }
+
+ @Override
+ public void onClick(float x, float y) {
+ // nothing
+ }
+
+ @Override
+ public void serializeToString(int indent, StringSerializer serializer) {
+ serializer.append(
+ indent, "ROUND_CLIP = [" + mWidth + ", " + mHeight
+ + ", " + mX1 + ", " + mY1
+ + ", " + mX2 + ", " + mY2 + "]");
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ShapeType.java
similarity index 67%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
copy to core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ShapeType.java
index 1f04a44..e425b4e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ShapeType.java
@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.internal.widget.remotecompose.core.operations.layout.modifiers;
-package com.android.systemui.activatable
-
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.TestScope
-
-/** Activates [activatable] for the duration of the test. */
-fun Activatable.activateIn(testScope: TestScope) {
- testScope.backgroundScope.launch { activate() }
+/**
+ * Known shapes, used for modifiers (clip/background/border)
+ */
+public class ShapeType {
+ public static int RECTANGLE = 0;
+ public static int CIRCLE = 1;
+ public static int ROUNDED_RECTANGLE = 2;
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java
new file mode 100644
index 0000000..c46c8d7
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout.modifiers;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+
+/**
+ * Set the width dimension on a component
+ */
+public class WidthModifierOperation extends DimensionModifierOperation {
+
+ public static final DimensionModifierOperation.Companion COMPANION =
+ new DimensionModifierOperation.Companion(Operations.MODIFIER_WIDTH, "WIDTH") {
+ @Override
+ public Operation construct(DimensionModifierOperation.Type type, float value) {
+ return new WidthModifierOperation(type, value);
+ }
+ };
+
+ public WidthModifierOperation(Type type, float value) {
+ super(type, value);
+ }
+
+ public WidthModifierOperation(Type type) {
+ super(type);
+ }
+
+ public WidthModifierOperation(float value) {
+ super(value);
+ }
+
+ @Override
+ public String toString() {
+ return "Width(" + mValue + ")";
+ }
+
+ @Override
+ public String serializedName() {
+ return "WIDTH";
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/utils/DebugLog.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/utils/DebugLog.java
new file mode 100644
index 0000000..7ccf7f4
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/utils/DebugLog.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout.utils;
+
+import java.util.ArrayList;
+
+/**
+ * Internal utility debug class
+ */
+public class DebugLog {
+
+ public static final boolean DEBUG_LAYOUT_ON = false;
+
+ public static class Node {
+ public Node parent;
+ public String name;
+ public String endString;
+ public ArrayList<Node> list = new ArrayList<>();
+
+ public Node(Node parent, String name) {
+ this.parent = parent;
+ this.name = name;
+ this.endString = name + " DONE";
+ if (parent != null) {
+ parent.add(this);
+ }
+ }
+
+ public void add(Node node) {
+ list.add(node);
+ }
+ }
+
+ public static class LogNode extends Node {
+ public LogNode(Node parent, String name) {
+ super(parent, name);
+ }
+ }
+
+ public static Node node = new Node(null, "Root");
+ public static Node currentNode = node;
+
+ public static void clear() {
+ node = new Node(null, "Root");
+ currentNode = node;
+ }
+
+ public static void s(StringValueSupplier valueSupplier) {
+ if (DEBUG_LAYOUT_ON) {
+ currentNode = new Node(currentNode, valueSupplier.getString());
+ }
+ }
+
+ public static void log(StringValueSupplier valueSupplier) {
+ if (DEBUG_LAYOUT_ON) {
+ new LogNode(currentNode, valueSupplier.getString());
+ }
+ }
+
+ public static void e() {
+ if (DEBUG_LAYOUT_ON) {
+ if (currentNode.parent != null) {
+ currentNode = currentNode.parent;
+ } else {
+ currentNode = node;
+ }
+ }
+ }
+
+ public static void e(StringValueSupplier valueSupplier) {
+ if (DEBUG_LAYOUT_ON) {
+ currentNode.endString = valueSupplier.getString();
+ if (currentNode.parent != null) {
+ currentNode = currentNode.parent;
+ } else {
+ currentNode = node;
+ }
+ }
+ }
+
+ public static void printNode(int indent, Node node, StringBuilder builder) {
+ if (DEBUG_LAYOUT_ON) {
+ StringBuilder indentationBuilder = new StringBuilder();
+ for (int i = 0; i < indent; i++) {
+ indentationBuilder.append("| ");
+ }
+ String indentation = indentationBuilder.toString();
+
+ if (node.list.size() > 0) {
+ builder.append(indentation).append(node.name).append("\n");
+ for (Node c : node.list) {
+ printNode(indent + 1, c, builder);
+ }
+ builder.append(indentation).append(node.endString).append("\n");
+ } else {
+ if (node instanceof LogNode) {
+ builder.append(indentation).append(" ").append(node.name).append("\n");
+ } else {
+ builder.append(indentation).append("-- ").append(node.name)
+ .append(" : ").append(node.endString).append("\n");
+ }
+ }
+ }
+ }
+
+ public static void display() {
+ if (DEBUG_LAYOUT_ON) {
+ StringBuilder builder = new StringBuilder();
+ printNode(0, node, builder);
+ System.out.println("\n" + builder.toString());
+ }
+ }
+}
+
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/utils/StringValueSupplier.java
similarity index 68%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
copy to core/java/com/android/internal/widget/remotecompose/core/operations/layout/utils/StringValueSupplier.java
index 1f04a44..79ef16b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/utils/StringValueSupplier.java
@@ -13,13 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.internal.widget.remotecompose.core.operations.layout.utils;
-package com.android.systemui.activatable
-
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.TestScope
-
-/** Activates [activatable] for the duration of the test. */
-fun Activatable.activateIn(testScope: TestScope) {
- testScope.backgroundScope.launch { activate() }
+/**
+ * Basic interface for a lambda (used for logging)
+ */
+public interface StringValueSupplier {
+ /**
+ * returns a string value
+ * @return a string
+ */
+ String getString();
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java b/core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java
index a7d0ac6..8186192 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java
@@ -695,6 +695,29 @@
}
/**
+ * Set the color based the R,G,B,A values
+ * @param r red (0 to 255)
+ * @param g green (0 to 255)
+ * @param b blue (0 to 255)
+ * @param a alpha (0 to 255)
+ */
+ public void setColor(int r, int g, int b, int a) {
+ int color = (a << 24) | (r << 16) | (g << 8) | b;
+ setColor(color);
+ }
+
+ /**
+ * Set the color based the R,G,B,A values
+ * @param r red (0.0 to 1.0)
+ * @param g green (0.0 to 1.0)
+ * @param b blue (0.0 to 1.0)
+ * @param a alpha (0.0 to 1.0)
+ */
+ public void setColor(float r, float g, float b, float a) {
+ setColor((int) r * 255, (int) g * 255, (int) b * 255, (int) a * 255);
+ }
+
+ /**
* Set the Color based on ID
* @param color
*/
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntFloatMap.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntFloatMap.java
index 23c3ec5..b2d714e 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntFloatMap.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntFloatMap.java
@@ -54,7 +54,7 @@
/**
* Put a item in the map
*
- * @param key item'values key
+ * @param key item's key
* @param value item's value
* @return old value if exist
*/
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntIntMap.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntIntMap.java
index 221014c..606dc78 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntIntMap.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntIntMap.java
@@ -53,7 +53,7 @@
/**
* Put a item in the map
*
- * @param key item'values key
+ * @param key item's key
* @param value item's value
* @return old value if exist
*/
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntegerExpressionEvaluator.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntegerExpressionEvaluator.java
index 4c1389c..a4fce80 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntegerExpressionEvaluator.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntegerExpressionEvaluator.java
@@ -400,8 +400,7 @@
-1, // no op
2, 2, 2, 2, 2, // + - * / %
2, 2, 2, 2, 2, 2, 2, 2, 2, //<<, >> , >>> , | , &, ^, min max
- 1, 1, 1, 1, 1, 1, // neg, abs, ++, -- , not , sign
-
+ 1, 1, 1, 1, 1, 1, // neg, abs, ++, -- , not , sign
3, 3, 3, // clamp, ifElse, mad,
0, 0, 0 // mad, ?:,
// a[0],a[1],a[2]
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/StringSerializer.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/StringSerializer.java
new file mode 100644
index 0000000..fb90781
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/StringSerializer.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.utilities;
+
+/**
+ * Utility serializer maintaining an indent buffer
+ */
+public class StringSerializer {
+ StringBuffer mBuffer = new StringBuffer();
+ String mIndentBuffer = " ";
+
+ /**
+ * Append some content to the current buffer
+ * @param indent the indentation level to use
+ * @param content content to append
+ */
+ public void append(int indent, String content) {
+ String indentation = mIndentBuffer.substring(0, indent);
+ mBuffer.append(indentation);
+ mBuffer.append(indentation);
+ mBuffer.append(content);
+ mBuffer.append("\n");
+ }
+
+ /**
+ * Reset the buffer
+ */
+ public void reset() {
+ mBuffer = new StringBuffer();
+ }
+
+ /**
+ * Return a string representation of the buffer
+ * @return string representation
+ */
+ public String toString() {
+ return mBuffer.toString();
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/GeneralEasing.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/GeneralEasing.java
index 693deaf..50a7d59 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/GeneralEasing.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/GeneralEasing.java
@@ -18,7 +18,7 @@
/**
* Provides and interface to create easing functions
*/
-public class GeneralEasing extends Easing{
+public class GeneralEasing extends Easing{
float[] mEasingData = new float[0];
Easing mEasingCurve = new CubicEasing(CUBIC_STANDARD);
diff --git a/core/java/com/android/internal/widget/remotecompose/player/RemoteComposeDocument.java b/core/java/com/android/internal/widget/remotecompose/player/RemoteComposeDocument.java
index a42c584..65a337e 100644
--- a/core/java/com/android/internal/widget/remotecompose/player/RemoteComposeDocument.java
+++ b/core/java/com/android/internal/widget/remotecompose/player/RemoteComposeDocument.java
@@ -18,6 +18,7 @@
import com.android.internal.widget.remotecompose.core.CoreDocument;
import com.android.internal.widget.remotecompose.core.RemoteComposeBuffer;
import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.operations.layout.Component;
import java.io.InputStream;
@@ -113,5 +114,13 @@
return mDocument.getNamedColors();
}
+ /**
+ * Return a component associated with id
+ * @param id the component id
+ * @return the corresponding component or null if not found
+ */
+ public Component getComponent(int id) {
+ return mDocument.getComponent(id);
+ }
}
diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java
index 39a770a..e01dd17 100644
--- a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java
+++ b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java
@@ -65,6 +65,21 @@
this.mCanvas = canvas;
}
+ @Override
+ public void save() {
+ mCanvas.save();
+ }
+
+ @Override
+ public void saveLayer(float x, float y, float width, float height) {
+ mCanvas.saveLayer(x, y, x + width, y + height, mPaint);
+ }
+
+ @Override
+ public void restore() {
+ mCanvas.restore();
+ }
+
/**
* Draw an image onto the canvas
*
@@ -613,6 +628,19 @@
}
@Override
+ public void roundedClipRect(float width, float height,
+ float topStart, float topEnd,
+ float bottomStart, float bottomEnd) {
+ Path roundedPath = new Path();
+ float[] radii = new float[] { topStart, topStart,
+ topEnd, topEnd, bottomEnd, bottomEnd, bottomStart, bottomStart};
+
+ roundedPath.addRoundRect(0f, 0f, width, height,
+ radii, android.graphics.Path.Direction.CW);
+ mCanvas.clipPath(roundedPath);
+ }
+
+ @Override
public void clipPath(int pathId, int regionOp) {
Path path = getPath(pathId, 0, 1);
if (regionOp == ClipPath.DIFFERENCE) {
diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java b/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java
index a2f79cc..0d7f97a 100644
--- a/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java
+++ b/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java
@@ -215,6 +215,7 @@
}
int w = measureDimension(widthMeasureSpec, mDocument.getWidth());
int h = measureDimension(heightMeasureSpec, mDocument.getHeight());
+ mDocument.getDocument().invalidateMeasure();
if (!USE_VIEW_AREA_CLICK) {
if (mDocument.getDocument().getContentSizing() == RootContentBehavior.SIZING_SCALE) {
@@ -235,6 +236,8 @@
if (mDocument == null) {
return;
}
+ mARContext.setAnimationEnabled(true);
+ mARContext.currentTime = System.currentTimeMillis();
mARContext.setDebug(mDebug);
mARContext.useCanvas(canvas);
mARContext.mWidth = getWidth();
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index ca984c0..2abdd57 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -258,6 +258,7 @@
"com_android_internal_content_om_OverlayManagerImpl.cpp",
"com_android_internal_net_NetworkUtilsInternal.cpp",
"com_android_internal_os_ClassLoaderFactory.cpp",
+ "com_android_internal_os_DebugStore.cpp",
"com_android_internal_os_FuseAppLoop.cpp",
"com_android_internal_os_KernelAllocationStats.cpp",
"com_android_internal_os_KernelCpuBpfTracking.cpp",
@@ -315,6 +316,7 @@
"libcrypto",
"libcutils",
"libdebuggerd_client",
+ "libdebugstore_cxx",
"libutils",
"libbinder",
"libbinderdebug",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index ed59327..03b5143a 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -202,6 +202,7 @@
extern int register_com_android_internal_content_om_OverlayManagerImpl(JNIEnv* env);
extern int register_com_android_internal_net_NetworkUtilsInternal(JNIEnv* env);
extern int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env);
+extern int register_com_android_internal_os_DebugStore(JNIEnv* env);
extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env);
extern int register_com_android_internal_os_KernelAllocationStats(JNIEnv* env);
extern int register_com_android_internal_os_KernelCpuBpfTracking(JNIEnv* env);
@@ -1599,6 +1600,7 @@
REG_JNI(register_com_android_internal_content_om_OverlayManagerImpl),
REG_JNI(register_com_android_internal_net_NetworkUtilsInternal),
REG_JNI(register_com_android_internal_os_ClassLoaderFactory),
+ REG_JNI(register_com_android_internal_os_DebugStore),
REG_JNI(register_com_android_internal_os_LongArrayMultiStateCounter),
REG_JNI(register_com_android_internal_os_LongMultiStateCounter),
REG_JNI(register_com_android_internal_os_Zygote),
diff --git a/core/jni/com_android_internal_os_DebugStore.cpp b/core/jni/com_android_internal_os_DebugStore.cpp
new file mode 100644
index 0000000..874d6ea
--- /dev/null
+++ b/core/jni/com_android_internal_os_DebugStore.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <debugstore/debugstore_cxx_bridge.rs.h>
+#include <log/log.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedLocalRef.h>
+#include <nativehelper/ScopedUtfChars.h>
+
+#include <iterator>
+#include <sstream>
+#include <vector>
+
+#include "core_jni_helpers.h"
+
+namespace android {
+
+static struct {
+ jmethodID mGet;
+ jmethodID mSize;
+} gListClassInfo;
+
+static std::vector<std::string> list_to_vector(JNIEnv* env, jobject jList) {
+ std::vector<std::string> vec;
+ jint size = env->CallIntMethod(jList, gListClassInfo.mSize);
+ if (size % 2 != 0) {
+ std::ostringstream oss;
+
+ std::copy(vec.begin(), vec.end(), std::ostream_iterator<std::string>(oss, ", "));
+ ALOGW("DebugStore list size is odd: %d, elements: %s", size, oss.str().c_str());
+
+ return vec;
+ }
+
+ vec.reserve(size);
+
+ for (jint i = 0; i < size; i++) {
+ ScopedLocalRef<jstring> jEntry(env,
+ reinterpret_cast<jstring>(
+ env->CallObjectMethod(jList, gListClassInfo.mGet,
+ i)));
+ ScopedUtfChars cEntry(env, jEntry.get());
+ vec.emplace_back(cEntry.c_str());
+ }
+ return vec;
+}
+
+static void com_android_internal_os_DebugStore_endEvent(JNIEnv* env, jclass clazz, jlong eventId,
+ jobject jAttributeList) {
+ auto attributes = list_to_vector(env, jAttributeList);
+ debugstore::debug_store_end(static_cast<uint64_t>(eventId), attributes);
+}
+
+static jlong com_android_internal_os_DebugStore_beginEvent(JNIEnv* env, jclass clazz,
+ jstring jeventName,
+ jobject jAttributeList) {
+ ScopedUtfChars eventName(env, jeventName);
+ auto attributes = list_to_vector(env, jAttributeList);
+ jlong eventId =
+ static_cast<jlong>(debugstore::debug_store_begin(eventName.c_str(), attributes));
+ return eventId;
+}
+
+static void com_android_internal_os_DebugStore_recordEvent(JNIEnv* env, jclass clazz,
+ jstring jeventName,
+ jobject jAttributeList) {
+ ScopedUtfChars eventName(env, jeventName);
+ auto attributes = list_to_vector(env, jAttributeList);
+ debugstore::debug_store_record(eventName.c_str(), attributes);
+}
+
+static const JNINativeMethod gDebugStoreMethods[] = {
+ /* name, signature, funcPtr */
+ {"beginEventNative", "(Ljava/lang/String;Ljava/util/List;)J",
+ (void*)com_android_internal_os_DebugStore_beginEvent},
+ {"endEventNative", "(JLjava/util/List;)V",
+ (void*)com_android_internal_os_DebugStore_endEvent},
+ {"recordEventNative", "(Ljava/lang/String;Ljava/util/List;)V",
+ (void*)com_android_internal_os_DebugStore_recordEvent},
+};
+
+int register_com_android_internal_os_DebugStore(JNIEnv* env) {
+ int res = RegisterMethodsOrDie(env, "com/android/internal/os/DebugStore", gDebugStoreMethods,
+ NELEM(gDebugStoreMethods));
+ jclass listClass = FindClassOrDie(env, "java/util/List");
+ gListClassInfo.mGet = GetMethodIDOrDie(env, listClass, "get", "(I)Ljava/lang/Object;");
+ gListClassInfo.mSize = GetMethodIDOrDie(env, listClass, "size", "()I");
+
+ return res;
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/core/proto/android/providers/settings/system.proto b/core/proto/android/providers/settings/system.proto
index e5ced25..e795e809 100644
--- a/core/proto/android/providers/settings/system.proto
+++ b/core/proto/android/providers/settings/system.proto
@@ -69,6 +69,7 @@
// 0 = no, 1 = yes
optional SettingProto window_orientation_listener_log = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto show_key_presses = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto touchpad_visualizer = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
optional DevOptions developer_options = 7;
diff --git a/core/res/Android.bp b/core/res/Android.bp
index 9207aa8..e900eb2 100644
--- a/core/res/Android.bp
+++ b/core/res/Android.bp
@@ -164,6 +164,7 @@
"com.android.window.flags.window-aconfig",
"android.permission.flags-aconfig",
"android.os.flags-aconfig",
+ "android.media.tv.flags-aconfig",
],
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index f3dac23..50727a2 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -5609,7 +5609,8 @@
@hide
-->
<permission android:name="android.permission.ALWAYS_BOUND_TV_INPUT"
- android:protectionLevel="signature|privileged|vendorPrivileged" />
+ android:protectionLevel="signature|privileged|vendorPrivileged"
+ android:featureFlag="android.media.tv.flags.tis_always_bound_permission"/>
<!-- Must be required by a {@link android.media.tv.interactive.TvInteractiveAppService}
to ensure that only the system can bind to it.
@@ -6107,9 +6108,8 @@
android:description="@string/permdesc_deliverCompanionMessages"
android:protectionLevel="normal" />
- <!-- @hide @FlaggedApi("android.companion.flags.companion_transport_apis")
- Allows an application to send and receive messages via CDM transports.
- -->
+ <!-- Allows an application to send and receive messages via CDM transports.
+ @hide -->
<permission android:name="android.permission.USE_COMPANION_TRANSPORTS"
android:protectionLevel="signature" />
diff --git a/core/res/TEST_MAPPING b/core/res/TEST_MAPPING
index 4d09076..0e01a2a 100644
--- a/core/res/TEST_MAPPING
+++ b/core/res/TEST_MAPPING
@@ -11,5 +11,22 @@
}
]
}
+ ],
+ // v2/sysui/suite/test-mapping-sysui-screenshot-test
+ "sysui-screenshot-test": [
+ {
+ "name": "SystemUIGoogleScreenshotTests",
+ "options": [
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.Postsubmit"
+ }
+ ]
+ }
]
-}
\ No newline at end of file
+}
diff --git a/core/res/res/drawable/ic_call_answer_video.xml b/core/res/res/drawable/ic_call_answer_video.xml
index 77c8892..79af247 100644
--- a/core/res/res/drawable/ic_call_answer_video.xml
+++ b/core/res/res/drawable/ic_call_answer_video.xml
@@ -16,8 +16,8 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
- android:viewportWidth="20"
- android:viewportHeight="20"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
android:tint="?android:attr/colorControlNormal"
android:autoMirrored="true">
<path
diff --git a/core/res/res/drawable/ic_zen_mode_icon_ball_sports.xml b/core/res/res/drawable/ic_zen_mode_icon_ball_sports.xml
new file mode 100644
index 0000000..fdf0bcf
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_ball_sports.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M368,956L298,916L418,708L350,668L290,772L220,732L426,376Q388,337 369,287Q350,237 350,184Q350,148 359,112.5Q368,77 388,44L388,44L456,84L456,84Q442,107 436,131.5Q430,156 430,182Q430,235 456,281.5Q482,328 530,356L620,408Q682,444 711,511.5Q740,579 740,638Q740,676 730,712Q720,748 702,780L702,780L632,740L632,740Q646,716 652,691Q658,666 658,640Q658,608 649,578Q640,548 620,522L368,956ZM640,360Q607,360 583.5,336.5Q560,313 560,280Q560,247 583.5,223.5Q607,200 640,200Q673,200 696.5,223.5Q720,247 720,280Q720,313 696.5,336.5Q673,360 640,360ZM540,160Q514,160 497,142Q480,124 480,100Q480,74 498,57Q516,40 540,40Q566,40 583,58Q600,76 600,100Q600,126 582,143Q564,160 540,160Z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_beach.xml b/core/res/res/drawable/ic_zen_mode_icon_beach.xml
new file mode 100644
index 0000000..a42d9fd
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_beach.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M784,840L530,586L586,530L840,784L784,840ZM238,812Q178,752 149,677Q120,602 120,524Q120,446 149,372Q178,298 238,238Q298,178 372.5,148.5Q447,119 525,119Q603,119 677.5,148.5Q752,178 812,238L238,812ZM246,690L300,636Q284,615 269.5,593Q255,571 243,549Q231,527 222,505Q213,483 206,462Q195,521 204.5,580Q214,639 246,690ZM358,580L580,356Q537,323 493.5,302.5Q450,282 412,274.5Q374,267 343.5,272Q313,277 296,294Q279,312 274,342.5Q269,373 276.5,411.5Q284,450 304.5,493Q325,536 358,580ZM636,300L692,246Q639,214 580,204Q521,194 462,206Q484,213 506,222Q528,231 550,242.5Q572,254 593.5,268.5Q615,283 636,300Z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_camping.xml b/core/res/res/drawable/ic_zen_mode_icon_camping.xml
new file mode 100644
index 0000000..1797ebd
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_camping.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M80,880L80,694L430,222L360,128L424,80L480,155L536,80L600,128L530,222L880,694L880,880L80,880ZM480,289L160,720L160,800L280,800L480,520L680,800L800,800L800,720L480,289ZM378,800L582,800L480,658L378,800ZM480,520L680,800L680,800L680,800L480,520L280,800L280,800L280,800L480,520Z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_gaming.xml b/core/res/res/drawable/ic_zen_mode_icon_gaming.xml
new file mode 100644
index 0000000..8bea9ae
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_gaming.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M182,760Q131,760 103,724.5Q75,689 82,638L124,338Q133,278 177.5,239Q222,200 282,200L678,200Q738,200 782.5,239Q827,278 836,338L878,638Q885,689 857,724.5Q829,760 778,760Q757,760 739,752.5Q721,745 706,730L616,640L344,640L254,730Q239,745 221,752.5Q203,760 182,760ZM198,674L312,560L648,560L762,674Q764,676 778,680Q789,680 795.5,673.5Q802,667 800,656L756,348Q752,319 730,299.5Q708,280 678,280L282,280Q252,280 230,299.5Q208,319 204,348L160,656Q158,667 164.5,673.5Q171,680 182,680Q184,680 198,674ZM680,520Q697,520 708.5,508.5Q720,497 720,480Q720,463 708.5,451.5Q697,440 680,440Q663,440 651.5,451.5Q640,463 640,480Q640,497 651.5,508.5Q663,520 680,520ZM600,400Q617,400 628.5,388.5Q640,377 640,360Q640,343 628.5,331.5Q617,320 600,320Q583,320 571.5,331.5Q560,343 560,360Q560,377 571.5,388.5Q583,400 600,400ZM310,520L370,520L370,450L440,450L440,390L370,390L370,320L310,320L310,390L240,390L240,450L310,450L310,520ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480L480,480Z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_golf.xml b/core/res/res/drawable/ic_zen_mode_icon_golf.xml
new file mode 100644
index 0000000..d899c5b
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_golf.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M780,840Q755,840 737.5,822.5Q720,805 720,780Q720,755 737.5,737.5Q755,720 780,720Q805,720 822.5,737.5Q840,755 840,780Q840,805 822.5,822.5Q805,840 780,840ZM400,880Q300,880 230,856.5Q160,833 160,800Q160,777 193,759Q226,741 280,730L280,800L360,800L360,80L680,236L440,360L440,722Q526,727 583,748.5Q640,770 640,800Q640,833 570,856.5Q500,880 400,880Z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_gym.xml b/core/res/res/drawable/ic_zen_mode_icon_gym.xml
new file mode 100644
index 0000000..585e564
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_gym.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M536,876L480,820L622,678L282,338L140,480L84,424L140,366L84,310L168,226L112,168L168,112L226,168L310,84L366,140L424,84L480,140L338,282L678,622L820,480L876,536L820,594L876,650L792,734L848,792L792,848L734,792L650,876L594,820L536,876Z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_hiking.xml b/core/res/res/drawable/ic_zen_mode_icon_hiking.xml
new file mode 100644
index 0000000..d2b8c85
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_hiking.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M280,920L403,298Q409,269 430,254.5Q451,240 474,240Q497,240 516.5,250Q536,260 548,280L588,344Q606,373 634.5,396.5Q663,420 700,431L700,360L760,360L760,920L700,920L700,514Q652,503 611,479Q570,455 540,420L516,540L600,620L600,920L520,920L520,680L436,600L364,920L280,920ZM297,525L212,509Q196,506 187,492.5Q178,479 181,462L211,305Q217,273 245,254.5Q273,236 305,242L351,251L297,525ZM540,220Q507,220 483.5,196.5Q460,173 460,140Q460,107 483.5,83.5Q507,60 540,60Q573,60 596.5,83.5Q620,107 620,140Q620,173 596.5,196.5Q573,220 540,220Z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_martial_arts.xml b/core/res/res/drawable/ic_zen_mode_icon_martial_arts.xml
new file mode 100644
index 0000000..7cabd86
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_martial_arts.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M400,880L380,520L253,447L239,499L320,640L251,680L152,510L200,338L430,206L320,96L376,40L560,223L416,306L464,348L792,80L840,136L500,480L480,880L400,880ZM200,280Q167,280 143.5,256.5Q120,233 120,200Q120,167 143.5,143.5Q167,120 200,120Q233,120 256.5,143.5Q280,167 280,200Q280,233 256.5,256.5Q233,280 200,280Z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_swimming.xml b/core/res/res/drawable/ic_zen_mode_icon_swimming.xml
new file mode 100644
index 0000000..465a02a
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_swimming.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M80,840L80,760Q118,760 137,740Q156,720 212,720Q268,720 289,740Q310,760 346,760Q382,760 403,740Q424,720 480,720Q536,720 557,740Q578,760 614,760Q650,760 671,740Q692,720 748,720Q804,720 823,740Q842,760 880,760L880,840Q821,840 802.5,820Q784,800 748,800Q712,800 691,820Q670,840 614,840Q558,840 537,820Q516,800 480,800Q444,800 423,820Q402,840 346,840Q290,840 269,820Q248,800 212,800Q176,800 157.5,820Q139,840 80,840ZM80,660L80,580Q118,580 137,560Q156,540 212,540Q268,540 289.5,560Q311,580 346,580Q382,580 403,560Q424,540 480,540Q536,540 557,560Q578,580 614,580Q650,580 671,560Q692,540 748,540Q804,540 823,560Q842,580 880,580L880,660Q821,660 802.5,640Q784,620 748,620Q712,620 692.5,640Q673,660 614,660Q557,660 536.5,640Q516,620 480,620Q442,620 423.5,640Q405,660 346,660Q287,660 267.5,640Q248,620 212,620Q176,620 157.5,640Q139,660 80,660ZM276,456L409,323L369,283Q336,250 299,235Q262,220 208,220L208,120Q283,120 332,136.5Q381,153 428,200L684,456Q667,467 651,473.5Q635,480 614,480Q578,480 557,460Q536,440 480,440Q424,440 403,460Q382,480 346,480Q325,480 309,473.5Q293,467 276,456ZM668,120Q710,120 739,149.5Q768,179 768,220Q768,262 739,291Q710,320 668,320Q626,320 597,291Q568,262 568,220Q568,179 597,149.5Q626,120 668,120Z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_work.xml b/core/res/res/drawable/ic_zen_mode_icon_work.xml
new file mode 100644
index 0000000..7820458
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_work.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M160,840Q127,840 103.5,816.5Q80,793 80,760L80,320Q80,287 103.5,263.5Q127,240 160,240L320,240L320,160Q320,127 343.5,103.5Q367,80 400,80L560,80Q593,80 616.5,103.5Q640,127 640,160L640,240L800,240Q833,240 856.5,263.5Q880,287 880,320L880,760Q880,793 856.5,816.5Q833,840 800,840L160,840ZM160,760L800,760Q800,760 800,760Q800,760 800,760L800,320Q800,320 800,320Q800,320 800,320L160,320Q160,320 160,320Q160,320 160,320L160,760Q160,760 160,760Q160,760 160,760ZM400,240L560,240L560,160Q560,160 560,160Q560,160 560,160L400,160Q400,160 400,160Q400,160 400,160L400,240ZM160,760Q160,760 160,760Q160,760 160,760L160,320Q160,320 160,320Q160,320 160,320L160,320Q160,320 160,320Q160,320 160,320L160,760Q160,760 160,760Q160,760 160,760Z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_workshop.xml b/core/res/res/drawable/ic_zen_mode_icon_workshop.xml
new file mode 100644
index 0000000..844c7b7
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_workshop.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M756,840L537,621L621,537L840,756L756,840ZM204,840L120,756L396,480L328,412L300,440L249,389L249,471L221,499L100,378L128,350L210,350L160,300L302,158Q322,138 345,129Q368,120 392,120Q416,120 439,129Q462,138 482,158L390,250L440,300L412,328L480,396L570,306Q566,295 563.5,283Q561,271 561,259Q561,200 601.5,159.5Q642,119 701,119Q716,119 729.5,122Q743,125 757,131L658,230L730,302L829,203Q836,217 838.5,230.5Q841,244 841,259Q841,318 800.5,358.5Q760,399 701,399Q689,399 677,397Q665,395 654,390L204,840Z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_type_managed.xml b/core/res/res/drawable/ic_zen_mode_type_managed.xml
index 5e224eb..46fb435 100644
--- a/core/res/res/drawable/ic_zen_mode_type_managed.xml
+++ b/core/res/res/drawable/ic_zen_mode_type_managed.xml
@@ -21,5 +21,5 @@
android:viewportWidth="960">
<path
android:fillColor="@android:color/white"
- android:pathData="M234,684Q285,645 348,622.5Q411,600 480,600Q549,600 612,622.5Q675,645 726,684Q761,643 780.5,591Q800,539 800,480Q800,347 706.5,253.5Q613,160 480,160Q347,160 253.5,253.5Q160,347 160,480Q160,539 179.5,591Q199,643 234,684ZM480,520Q421,520 380.5,479.5Q340,439 340,380Q340,321 380.5,280.5Q421,240 480,240Q539,240 579.5,280.5Q620,321 620,380Q620,439 579.5,479.5Q539,520 480,520ZM480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880ZM480,800Q533,800 580,784.5Q627,769 666,740Q627,711 580,695.5Q533,680 480,680Q427,680 380,695.5Q333,711 294,740Q333,769 380,784.5Q427,800 480,800ZM480,440Q506,440 523,423Q540,406 540,380Q540,354 523,337Q506,320 480,320Q454,320 437,337Q420,354 420,380Q420,406 437,423Q454,440 480,440ZM480,380Q480,380 480,380Q480,380 480,380Q480,380 480,380Q480,380 480,380Q480,380 480,380Q480,380 480,380Q480,380 480,380Q480,380 480,380ZM480,740Q480,740 480,740Q480,740 480,740Q480,740 480,740Q480,740 480,740Q480,740 480,740Q480,740 480,740Q480,740 480,740Q480,740 480,740Z" />
+ android:pathData="M680,600Q638,600 609,571Q580,542 580,500Q580,458 609,429Q638,400 680,400Q722,400 751,429Q780,458 780,500Q780,542 751,571Q722,600 680,600ZM480,800L480,744Q480,720 492.5,699.5Q505,679 528,670Q564,655 602.5,647.5Q641,640 680,640Q719,640 757.5,647.5Q796,655 832,670Q855,679 867.5,699.5Q880,720 880,744L880,800L480,800ZM400,480Q334,480 287,433Q240,386 240,320Q240,254 287,207Q334,160 400,160Q466,160 513,207Q560,254 560,320Q560,386 513,433Q466,480 400,480ZM400,320Q400,320 400,320Q400,320 400,320Q400,320 400,320Q400,320 400,320Q400,320 400,320Q400,320 400,320Q400,320 400,320Q400,320 400,320ZM80,800L80,688Q80,654 97,625.5Q114,597 144,582Q204,552 268.5,536Q333,520 400,520Q435,520 470,526Q505,532 540,540Q523,557 506,574Q489,591 472,608Q454,603 436,601.5Q418,600 400,600Q342,600 286.5,614Q231,628 180,654Q170,659 165,668Q160,677 160,688L160,720L400,720L400,800L80,800ZM400,720Q400,720 400,720Q400,720 400,720Q400,720 400,720Q400,720 400,720L400,720L400,720Q400,720 400,720Q400,720 400,720Q400,720 400,720Q400,720 400,720ZM400,400Q433,400 456.5,376.5Q480,353 480,320Q480,287 456.5,263.5Q433,240 400,240Q367,240 343.5,263.5Q320,287 320,320Q320,353 343.5,376.5Q367,400 400,400Z" />
</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/tooltip_frame.xml b/core/res/res/drawable/tooltip_frame.xml
index 14130c8..e2618ca 100644
--- a/core/res/res/drawable/tooltip_frame.xml
+++ b/core/res/res/drawable/tooltip_frame.xml
@@ -17,5 +17,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="?attr/tooltipBackgroundColor" />
- <corners android:radius="@dimen/tooltip_corner_radius" />
-</shape>
\ No newline at end of file
+ <corners android:radius="?attr/tooltipCornerRadius" />
+</shape>
diff --git a/core/res/res/layout/tooltip.xml b/core/res/res/layout/tooltip.xml
index 376c5eb..5b6799e 100644
--- a/core/res/res/layout/tooltip.xml
+++ b/core/res/res/layout/tooltip.xml
@@ -27,10 +27,10 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/tooltip_margin"
- android:paddingStart="@dimen/tooltip_horizontal_padding"
- android:paddingEnd="@dimen/tooltip_horizontal_padding"
- android:paddingTop="@dimen/tooltip_vertical_padding"
- android:paddingBottom="@dimen/tooltip_vertical_padding"
+ android:paddingStart="?attr/tooltipHorizontalPadding"
+ android:paddingEnd="?attr/tooltipHorizontalPadding"
+ android:paddingTop="?attr/tooltipVerticalPadding"
+ android:paddingBottom="?attr/tooltipVerticalPadding"
android:maxWidth="256dp"
android:background="?android:attr/tooltipFrameBackground"
android:textAppearance="@style/TextAppearance.Tooltip"
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 732b81b..b353893 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -202,7 +202,7 @@
<string name="ssl_ca_cert_noti_managed" msgid="217337232273211674">"بواسطة <xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string>
<string name="work_profile_deleted" msgid="5891181538182009328">"تم حذف ملف العمل."</string>
<string name="work_profile_deleted_details" msgid="3773706828364418016">"تطبيق المشرف لملف العمل مفقود أو تالف لذا تم حذف ملف العمل والبيانات ذات الصلة. اتصل بالمشرف للحصول على المساعدة."</string>
- <string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"لم يعد ملفك الشخصي للعمل متاحًا على هذا الجهاز"</string>
+ <string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"لم يعد ملف العمل الخاص بك متاحًا على هذا الجهاز"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"تم إجراء محاولات كثيرة جدًا لإدخال كلمة المرور"</string>
<string name="device_ownership_relinquished" msgid="4080886992183195724">"تنازل المشرف عن الجهاز للاستخدام الشخصي"</string>
<string name="private_space_deleted_by_admin" msgid="1484365588862066939">"تمت إزالة المساحة الخاصّة"</string>
@@ -224,7 +224,7 @@
<string name="factory_reset_message" msgid="2657049595153992213">"تعذّر استخدام تطبيق المشرف. سيتم محو بيانات جهازك الآن.\n\nإذا كانت لديك أسئلة، اتصل بمشرف مؤسستك."</string>
<string name="printing_disabled_by" msgid="3517499806528864633">"تم إيقاف الطباعة بواسطة <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="personal_apps_suspension_title" msgid="7561416677884286600">"تفعيل ملف العمل"</string>
- <string name="personal_apps_suspension_text" msgid="6115455688932935597">"تم حظر تطبيقاتك الشخصية إلى أن تفعِّل ملفك الشخصي للعمل."</string>
+ <string name="personal_apps_suspension_text" msgid="6115455688932935597">"تم حظر تطبيقاتك الشخصية إلى أن تفعِّل ملف العمل الخاص بك."</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"سيتم حظر التطبيقات الشخصية في <xliff:g id="DATE">%1$s</xliff:g> في <xliff:g id="TIME">%2$s</xliff:g>. لا يسمح مشرف تكنولوجيا المعلومات في مؤسستك بإيقاف ملف العمل أكثر من <xliff:g id="NUMBER">%3$d</xliff:g> يوم."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"تفعيل"</string>
<string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"المكالمات والرسائل غير مفعّلة"</string>
@@ -701,12 +701,12 @@
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"رمز بصمة الإصبع"</string>
<string name="device_unlock_notification_name" msgid="2632928999862915709">"فتح قفل الجهاز"</string>
<string name="alternative_unlock_setup_notification_title" msgid="6241508547901933544">"تجربة طريقة أخرى لفتح القفل"</string>
- <string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"استخدِم ميزة \"فتح الجهاز بالتعرف على الوجه\" عندما لا يتم التعرف على بصمة إصبعك، مثلاً عندما تكون أصابعك مبتلة."</string>
+ <string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"استخدِم ميزة \"فتح الجهاز ببصمة الوجه\" عندما لا يتم التعرف على بصمة إصبعك، مثلاً عندما تكون أصابعك مبتلة."</string>
<string name="alternative_fp_setup_notification_content" msgid="7454096947415721639">"استخدِم ميزة \"فتح الجهاز ببصمة الإصبع\" عندما لا يتم التعرف على وجهك، مثلاً عند عدم وجود ضوء كافٍ."</string>
- <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"فتح الجهاز بالتعرف على الوجه"</string>
- <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"مشكلة متعلّقة بميزة \"فتح الجهاز بالتعرف على الوجه\""</string>
+ <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"فتح الجهاز ببصمة الوجه"</string>
+ <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"مشكلة متعلّقة بميزة \"فتح الجهاز ببصمة الوجه\""</string>
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"انقر لحذف نموذج الوجه ثم أضِف نموذجًا لوجهك مرة أخرى."</string>
- <string name="face_sensor_privacy_enabled" msgid="7407126963510598508">"لاستخدام ميزة \"فتح الجهاز بالتعرف على الوجه\"، عليك منح إذن "<b>"الوصول إلى الكاميرا"</b>" في الإعدادات > الخصوصية."</string>
+ <string name="face_sensor_privacy_enabled" msgid="7407126963510598508">"لاستخدام ميزة \"فتح الجهاز ببصمة الوجه\"، عليك منح إذن "<b>"الوصول إلى الكاميرا"</b>" في الإعدادات > الخصوصية."</string>
<string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"فتح الجهاز ببصمة الإصبع"</string>
<string name="fingerprint_recalibrate_notification_title" msgid="2406561052064558497">"لا يمكن استخدام مستشعر بصمات الإصبع"</string>
<string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"يُرجى التواصل مع مقدِّم خدمات إصلاح."</string>
@@ -740,19 +740,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"يتعذّر التحقُّق من الوجه. الجهاز غير مُتاح."</string>
- <string name="face_error_timeout" msgid="2598544068593889762">"جرِّب \"فتح الجهاز بالتعرف على الوجه\" مرة أخرى."</string>
+ <string name="face_error_timeout" msgid="2598544068593889762">"جرِّب \"فتح الجهاز ببصمة الوجه\" مرة أخرى."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"يتعذَّر تخزين بيانات الوجه الجديد. احذف الوجه القديم أولاً."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"تمّ إلغاء عملية مصادقة الوجه."</string>
- <string name="face_error_user_canceled" msgid="5766472033202928373">"ألغى المستخدم ميزة \"فتح الجهاز بالتعرف على الوجه\"."</string>
+ <string name="face_error_user_canceled" msgid="5766472033202928373">"ألغى المستخدم ميزة \"فتح الجهاز ببصمة الوجه\"."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"تمّ إجراء محاولات كثيرة. أعِد المحاولة لاحقًا."</string>
- <string name="face_error_lockout_permanent" msgid="8533257333130473422">"أجريت محاولات كثيرة جدًا. ميزة \"فتح الجهاز بالتعرف على الوجه\" غير متاحة."</string>
+ <string name="face_error_lockout_permanent" msgid="8533257333130473422">"أجريت محاولات كثيرة جدًا. ميزة \"فتح الجهاز ببصمة الوجه\" غير متاحة."</string>
<string name="face_error_lockout_screen_lock" msgid="5062609811636860928">"تم إجراء عدد كبير جدًا من المحاولات. أدخِل قفل الشاشة بدلاً من ذلك."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"يتعذّر التحقق من الوجه. حاول مرة أخرى."</string>
- <string name="face_error_not_enrolled" msgid="1134739108536328412">"لم يسبق لك إعداد ميزة \"فتح الجهاز بالتعرف على الوجه\"."</string>
- <string name="face_error_hw_not_present" msgid="7940978724978763011">"ميزة \"فتح الجهاز بالتعرف على الوجه\" غير متوافقة على هذا الجهاز."</string>
+ <string name="face_error_not_enrolled" msgid="1134739108536328412">"لم يسبق لك إعداد ميزة \"فتح الجهاز ببصمة الوجه\"."</string>
+ <string name="face_error_hw_not_present" msgid="7940978724978763011">"ميزة \"فتح الجهاز ببصمة الوجه\" غير متوافقة على هذا الجهاز."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"تم إيقاف جهاز الاستشعار مؤقتًا."</string>
<string name="face_name_template" msgid="3877037340223318119">"الوجه <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="5854024256907828015">"فتح الجهاز بالتعرف على الوجه"</string>
+ <string name="face_app_setting_name" msgid="5854024256907828015">"فتح الجهاز ببصمة الوجه"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"استخدام ميزة \"فتح الجهاز بالتعرف على الوجه\" أو ميزة \"قفل الشاشة\""</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"استخدِم الوجه للمتابعة"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"استخدام ميزة \"فتح القفل بالوجه\" أو ميزة \"قفل الشاشة\" للمتابعة"</string>
@@ -1007,7 +1007,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"أعد المحاولة"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"أعد المحاولة"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"فتح القفل للوصول إلى جميع الميزات والبيانات"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"تم تجاوز الحد الأقصى لعدد محاولات فتح الجهاز بالتعرف على الوجه"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"تم تجاوز الحد الأقصى لعدد محاولات فتح الجهاز ببصمة الوجه"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1229301273156907613">"لا تتوفر شريحة SIM."</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="3986843848305639161">"لا تتوفر شريحة SIM في الجهاز اللوحي."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="3903140876952198273">"لا تتوفر شريحة SIM في جهاز Android TV."</string>
@@ -1077,7 +1077,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"توسيع منطقة فتح القفل."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"فتح القفل باستخدام التمرير."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"فتح القفل باستخدام النقش."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"فتح الجهاز بالتعرف على الوجه"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"فتح الجهاز ببصمة الوجه"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"فتح القفل باستخدام رمز PIN."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"فتح قفل رقم التعريف الشخصي لشريحة SIM."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"فتح قفل مفتاح PUK لشريحة SIM."</string>
@@ -1526,8 +1526,8 @@
<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="APP">%1$s</xliff:g> الإذن بالدخول\nإلى حساب <xliff:g id="ACCOUNT">%2$s</xliff:g>."</string>
- <string name="forward_intent_to_owner" msgid="4620359037192871015">"أنت تستخدم هذا التطبيق خارج ملفك الشخصي للعمل"</string>
- <string name="forward_intent_to_work" msgid="3620262405636021151">"أنت تستخدم هذا التطبيق في ملفك الشخصي للعمل"</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>
<string name="accessibility_binding_label" msgid="1974602776545801715">"سهولة الاستخدام"</string>
@@ -1656,7 +1656,7 @@
<string name="SetupCallDefault" msgid="5581740063237175247">"هل تريد قبول المكالمة؟"</string>
<string name="activity_resolver_use_always" msgid="5575222334666843269">"دائمًا"</string>
<string name="activity_resolver_use_once" msgid="948462794469672658">"مرة واحدة فقط"</string>
- <string name="activity_resolver_work_profiles_support" msgid="4071345609235361269">"لا يدعم %1$s الملفات الشخصية للعمل"</string>
+ <string name="activity_resolver_work_profiles_support" msgid="4071345609235361269">"لا يدعم %1$s ملفات العمل"</string>
<string name="default_audio_route_name" product="tablet" msgid="367936735632195517">"الجهاز اللوحي"</string>
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"التلفزيون"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"الهاتف"</string>
@@ -2228,7 +2228,7 @@
<string name="resolver_switch_on_work" msgid="4527096360772311894">"إلغاء الإيقاف المؤقت"</string>
<string name="resolver_no_work_apps_available" msgid="3298291360133337270">"ما مِن تطبيقات عمل."</string>
<string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"ما مِن تطبيقات شخصية."</string>
- <string name="miniresolver_open_work" msgid="6286176185835401931">"هل تريد فتح تطبيق \"<xliff:g id="APP">%s</xliff:g>\" في ملفك الشخصي للعمل؟"</string>
+ <string name="miniresolver_open_work" msgid="6286176185835401931">"هل تريد فتح تطبيق \"<xliff:g id="APP">%s</xliff:g>\" في ملف العمل الخاص بك؟"</string>
<string name="miniresolver_open_in_personal" msgid="807427577794490375">"هل تريد فتح المحتوى في تطبيق \"<xliff:g id="APP">%s</xliff:g>\" في الملف الشخصي؟"</string>
<string name="miniresolver_open_in_work" msgid="941341494673509916">"هل تريد فتح المحتوى في تطبيق \"<xliff:g id="APP">%s</xliff:g>\" في ملف العمل؟"</string>
<string name="miniresolver_call_in_work" msgid="528779988307529039">"هل تريد الاتصال من تطبيق العمل؟"</string>
@@ -2434,8 +2434,8 @@
<string name="fingerprint_dangling_notification_msg_2" msgid="7925203589860744456">"لا يمكن بعد الآن التعرّف على \"<xliff:g id="FINGERPRINT_0">%1$s</xliff:g>\" و\"<xliff:g id="FINGERPRINT_1">%2$s</xliff:g>\"."</string>
<string name="fingerprint_dangling_notification_msg_all_deleted_1" msgid="1824812666549916586">"لا يمكن بعد الآن التعرّف على \"<xliff:g id="FINGERPRINT">%s</xliff:g>\". يجب ضبط ميزة \"فتح الجهاز ببصمة الإصبع\" مجددًا."</string>
<string name="fingerprint_dangling_notification_msg_all_deleted_2" msgid="5974657382960155099">"لا يمكن بعد الآن التعرّف على \"<xliff:g id="FINGERPRINT_0">%1$s</xliff:g>\" و\"<xliff:g id="FINGERPRINT_1">%2$s</xliff:g>\". يجب ضبط ميزة \"فتح الجهاز ببصمة الإصبع\" مجددًا."</string>
- <string name="face_dangling_notification_title" msgid="947852541060975473">"إعادة إعداد ميزة \"فتح الجهاز بالتعرّف على الوجه\""</string>
- <string name="face_dangling_notification_msg" msgid="746235263598985384">"لا يمكن بعد الآن التعرّف على نموذج الوجه الخاص بك. يجب ضبط ميزة \"فتح الجهاز بالتعرّف على الوجه\" مجددًا."</string>
+ <string name="face_dangling_notification_title" msgid="947852541060975473">"إعادة إعداد ميزة \"فتح الجهاز ببصمة الوجه\""</string>
+ <string name="face_dangling_notification_msg" msgid="746235263598985384">"لا يمكن بعد الآن التعرّف على نموذج الوجه الخاص بك. يجب ضبط ميزة \"فتح الجهاز ببصمة الوجه\" مجددًا."</string>
<string name="biometric_dangling_notification_action_set_up" msgid="8246885009807817961">"إعداد"</string>
<string name="biometric_dangling_notification_action_not_now" msgid="8095249216864443491">"لاحقًا"</string>
<string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"تنبيه لـ \"<xliff:g id="USER_NAME">%s</xliff:g>\""</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 93976f9..86c4c35 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -2434,7 +2434,7 @@
<string name="face_dangling_notification_msg" msgid="746235263598985384">"Üz modeliniz artıq tanınmır. Üzlə Kilidaçmanı yenidən ayarlayın."</string>
<string name="biometric_dangling_notification_action_set_up" msgid="8246885009807817961">"Ayarlayın"</string>
<string name="biometric_dangling_notification_action_not_now" msgid="8095249216864443491">"İndi yox"</string>
- <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"<xliff:g id="USER_NAME">%s</xliff:g> üçün alarm"</string>
+ <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"<xliff:g id="USER_NAME">%s</xliff:g> üçün zəngli saat"</string>
<string name="bg_user_sound_notification_button_switch_user" msgid="3091969648572788946">"İstifadəçini dəyişin"</string>
<string name="bg_user_sound_notification_button_mute" msgid="4942158515665615243">"Susdurun"</string>
<string name="bg_user_sound_notification_message" msgid="8613881975316976673">"Susdurmaq üçün toxunun"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 78a74a8..c950d7c 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1067,7 +1067,7 @@
<string name="keyguard_accessibility_user_selector" msgid="1466067610235696600">"Biranje korisnika"</string>
<string name="keyguard_accessibility_status" msgid="6792745049712397237">"Status"</string>
<string name="keyguard_accessibility_camera" msgid="7862557559464986528">"Kamera"</string>
- <string name="keygaurd_accessibility_media_controls" msgid="2267379779900620614">"Upravljanje medijima"</string>
+ <string name="keygaurd_accessibility_media_controls" msgid="2267379779900620614">"Kontrole medija"</string>
<string name="keyguard_accessibility_widget_reorder_start" msgid="7066213328912939191">"Promjena rasporeda widgeta je počela."</string>
<string name="keyguard_accessibility_widget_reorder_end" msgid="1083806817600593490">"Promjena rasporeda widgeta je završena."</string>
<string name="keyguard_accessibility_widget_deleted" msgid="1509738950119878705">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> je izbrisan."</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 646e87d..a58b262 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -2434,7 +2434,7 @@
<string name="face_dangling_notification_msg" msgid="746235263598985384">"Your face model can no longer be recognised. Set up Face Unlock again."</string>
<string name="biometric_dangling_notification_action_set_up" msgid="8246885009807817961">"Set up"</string>
<string name="biometric_dangling_notification_action_not_now" msgid="8095249216864443491">"Not now"</string>
- <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"Alarm for <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"Alarm for: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="bg_user_sound_notification_button_switch_user" msgid="3091969648572788946">"Switch user"</string>
<string name="bg_user_sound_notification_button_mute" msgid="4942158515665615243">"Mute"</string>
<string name="bg_user_sound_notification_message" msgid="8613881975316976673">"Tap to mute sound"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 6f83d88..234eb7b 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -2434,7 +2434,7 @@
<string name="face_dangling_notification_msg" msgid="746235263598985384">"Your face model can no longer be recognised. Set up Face Unlock again."</string>
<string name="biometric_dangling_notification_action_set_up" msgid="8246885009807817961">"Set up"</string>
<string name="biometric_dangling_notification_action_not_now" msgid="8095249216864443491">"Not now"</string>
- <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"Alarm for <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"Alarm for: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="bg_user_sound_notification_button_switch_user" msgid="3091969648572788946">"Switch user"</string>
<string name="bg_user_sound_notification_button_mute" msgid="4942158515665615243">"Mute"</string>
<string name="bg_user_sound_notification_message" msgid="8613881975316976673">"Tap to mute sound"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 3f194fa..8c2a92e 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -2434,7 +2434,7 @@
<string name="face_dangling_notification_msg" msgid="746235263598985384">"Your face model can no longer be recognised. Set up Face Unlock again."</string>
<string name="biometric_dangling_notification_action_set_up" msgid="8246885009807817961">"Set up"</string>
<string name="biometric_dangling_notification_action_not_now" msgid="8095249216864443491">"Not now"</string>
- <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"Alarm for <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"Alarm for: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="bg_user_sound_notification_button_switch_user" msgid="3091969648572788946">"Switch user"</string>
<string name="bg_user_sound_notification_button_mute" msgid="4942158515665615243">"Mute"</string>
<string name="bg_user_sound_notification_message" msgid="8613881975316976673">"Tap to mute sound"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index b4dbd43..7f99750 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -622,7 +622,7 @@
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"désactiver le verrouillage de l\'écran"</string>
<string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Permet à l\'appli de désactiver le verrouillage des touches et toute mesure de sécurité par mot de passe associée. Par exemple, votre téléphone désactive le verrouillage des touches lorsque vous recevez un appel, puis le réactive lorsque vous raccrochez."</string>
<string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"demander la complexité du verrouillage d\'écran"</string>
- <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"Autorise l\'appli à apprendre le niveau de complexité de l\'écran de verrouillage (élevé, moyen, faible ou aucun), qui indique la gamme possible de longueur et de type de verrouillage d\'écran. L\'appli peut aussi suggérer aux utilisateurs de mettre à jour l\'écran de verrouillage afin d\'utiliser un certain niveau de complexité, mais ils peuvent ignorer la suggestion. Notez que le verrouillage d\'écran n\'est pas stocké en texte brut pour de manière à ce que l\'appli n\'ait pas accès au mot de passe exact."</string>
+ <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"Autorise l\'appli à apprendre le niveau de complexité du Verrouillage de l\'écran (élevé, moyen, faible ou aucun), ce qui indique les différentes possibilités de longueur et de type de verrouillage d\'écran. L\'appli peut aussi suggérer aux utilisateurs de mettre à jour le Verrouillage de l\'écran afin d\'atteindre un certain niveau de complexité, mais ces derniers peuvent ignorer la suggestion. Notez que le Verrouillage de l\'écran n\'est pas stocké en texte brut pour que l\'appli n\'ait pas accès au mot de passe exact."</string>
<string name="permlab_postNotification" msgid="4875401198597803658">"afficher les notifications"</string>
<string name="permdesc_postNotification" msgid="5974977162462877075">"Permet à l\'appli d\'afficher les notifications"</string>
<string name="permlab_turnScreenOn" msgid="219344053664171492">"allumer l\'écran"</string>
@@ -829,7 +829,7 @@
<string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"Permet au détenteur de commencer à afficher les renseignements sur les fonctionnalités d\'une appli."</string>
<string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"accéder aux données des capteurs à un taux d’échantillonnage élevé"</string>
<string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Permet à l’appli d’échantillonner les données des capteurs à une fréquence supérieure à 200 Hz"</string>
- <string name="permlab_updatePackagesWithoutUserAction" msgid="3363272609642618551">"Mettre à jour l\'appli sans intervention de l\'utilisateur"</string>
+ <string name="permlab_updatePackagesWithoutUserAction" msgid="3363272609642618551">"mettre à jour l\'appli sans intervention de l\'utilisateur"</string>
<string name="permdesc_updatePackagesWithoutUserAction" msgid="4567739631260526366">"Permet à une appli précédemment installée de se mettre à jour sans intervention de l\'utilisateur"</string>
<string name="permlab_writeVerificationStateE2eeContactKeys" msgid="3990742344778360457">"mettre à jour les états des vérifications des clés de contact chiffrées de bout en bout qui appartiennent à d\'autres applis"</string>
<string name="permdesc_writeVerificationStateE2eeContactKeys" msgid="8453156829747427041">"Autorise l\'appli à mettre à jour les états des vérifications des clés de contact chiffrées de bout en bout qui appartiennent à d\'autres applis"</string>
@@ -1417,7 +1417,7 @@
<string name="console_running_notification_title" msgid="6087888939261635904">"La console série est activée"</string>
<string name="console_running_notification_message" msgid="7892751888125174039">"La performance est réduite. Pour désactiver cette fonction, vérifier le programme d\'amorçage."</string>
<string name="mte_override_notification_title" msgid="4731115381962792944">"Extension MTE expérimentale activée"</string>
- <string name="mte_override_notification_message" msgid="2441170442725738942">"La performance et la stabilité pourraient être affectées. Redémarrez l\'appareil pour la désactiver. Si vous l\'activez au moyen de la propriété arm64.memtag.bootctl, définissez d\'abord celle-ci à « none »."</string>
+ <string name="mte_override_notification_message" msgid="2441170442725738942">"La performance et la stabilité pourraient être affectées. Redémarrez pour désactiver. Si vous l\'activez au moyen de la propriété arm64.memtag.bootctl, définissez d\'abord celle-ci à « none »."</string>
<string name="usb_contaminant_detected_title" msgid="4359048603069159678">"Liquide ou débris dans le port USB"</string>
<string name="usb_contaminant_detected_message" msgid="7346100585390795743">"Le port USB est désactivé automatiquement. Touchez ici pour en savoir plus."</string>
<string name="usb_contaminant_not_detected_title" msgid="2651167729563264053">"Autorisation d\'utiliser le port USB"</string>
@@ -1480,10 +1480,10 @@
<string name="ext_media_move_success_message" msgid="9159542002276982979">"Contenu déplacé vers <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_move_failure_title" msgid="3184577479181333665">"Impossible de déplacer le contenu"</string>
<string name="ext_media_move_failure_message" msgid="4197306718121869335">"Essayez de déplacer le contenu de nouveau"</string>
- <string name="ext_media_status_removed" msgid="241223931135751691">"Supprimée"</string>
+ <string name="ext_media_status_removed" msgid="241223931135751691">"Supprimé"</string>
<string name="ext_media_status_unmounted" msgid="8145812017295835941">"Éjectée"</string>
<string name="ext_media_status_checking" msgid="159013362442090347">"Vérification en cours…"</string>
- <string name="ext_media_status_mounted" msgid="3459448555811203459">"Prête"</string>
+ <string name="ext_media_status_mounted" msgid="3459448555811203459">"Prêt"</string>
<string name="ext_media_status_mounted_ro" msgid="1974809199760086956">"En lecture seule"</string>
<string name="ext_media_status_bad_removal" msgid="508448566481406245">"Retrait risqué"</string>
<string name="ext_media_status_unmountable" msgid="7043574843541087748">"Corrompue"</string>
@@ -1537,7 +1537,7 @@
<string name="vpn_title" msgid="5906991595291514182">"RPV activé"</string>
<string name="vpn_title_long" msgid="6834144390504619998">"RPV activé par <xliff:g id="APP">%s</xliff:g>"</string>
<string name="vpn_text" msgid="2275388920267251078">"Appuyez ici pour gérer le réseau."</string>
- <string name="vpn_text_long" msgid="278540576806169831">"Connecté à <xliff:g id="SESSION">%s</xliff:g>. Appuyez ici pour gérer le réseau."</string>
+ <string name="vpn_text_long" msgid="278540576806169831">"Connecté à <xliff:g id="SESSION">%s</xliff:g>. Touchez ici pour gérer le réseau."</string>
<string name="vpn_lockdown_connecting" msgid="6096725311950342607">"RPV permanent en cours de connexion…"</string>
<string name="vpn_lockdown_connected" msgid="2853127976590658469">"RPV permanent connecté"</string>
<string name="vpn_lockdown_disconnected" msgid="5573611651300764955">"Déconnecté du RPV permanent"</string>
@@ -2151,7 +2151,7 @@
<string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string>
<string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Désactiver"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"En savoir plus"</string>
- <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Les notifications améliorées ont remplacé les notifications adaptatives Android sous Android 12. Cette fonctionnalité vous présente des suggestions d\'actions et de réponses, et organise vos notifications.\n\nLes notifications améliorées peuvent accéder au contenu de toutes les notifications, y compris les renseignements personnels comme le nom des contacts et les messages. Cette fonctionnalité peut aussi fermer des notifications ou interagir avec elles, comme répondre aux appels téléphoniques et gérer le mode Ne pas déranger."</string>
+ <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Les notifications améliorées ont remplacé les notifications adaptatives Android sous Android 12. Cette fonctionnalité vous présente des suggestions d\'actions et de réponse, et organise vos notifications.\n\nLes notifications améliorées peuvent accéder au contenu de toutes les notifications, y compris les renseignements personnels comme le nom des contacts et les messages. Cette fonctionnalité peut aussi fermer des notifications ou interagir avec elles, comme répondre aux appels téléphoniques et gérer le mode Ne pas déranger."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notification d\'information du mode Routine"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Économiseur de pile activé"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Réduction de l\'utilisation de la pile pour en prolonger l\'autonomie"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index a81566c..b2e03f3 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -2434,7 +2434,7 @@
<string name="face_dangling_notification_msg" msgid="746235263598985384">"Ekki er hægt að bera kennsl á andlitslíkanið þitt lengur. Settu upp andlitskenni aftur."</string>
<string name="biometric_dangling_notification_action_set_up" msgid="8246885009807817961">"Setja upp"</string>
<string name="biometric_dangling_notification_action_not_now" msgid="8095249216864443491">"Ekki núna"</string>
- <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"Viðvörun fyrir <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"Viðvörun fyrir: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="bg_user_sound_notification_button_switch_user" msgid="3091969648572788946">"Skipta um notanda"</string>
<string name="bg_user_sound_notification_button_mute" msgid="4942158515665615243">"Þagga"</string>
<string name="bg_user_sound_notification_message" msgid="8613881975316976673">"Ýttu til að þagga hljóð"</string>
diff --git a/core/res/res/values-it-feminine/strings.xml b/core/res/res/values-it-feminine/strings.xml
index 407417d..141b467 100644
--- a/core/res/res/values-it-feminine/strings.xml
+++ b/core/res/res/values-it-feminine/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="relationTypeChild" msgid="9076258911292693601">"Figlia"</string>
<string name="relationTypeFriend" msgid="3192092625893980574">"Amica"</string>
<string name="relationTypeSpouse" msgid="6916682664436031703">"Moglie"</string>
</resources>
diff --git a/core/res/res/values-it-masculine/strings.xml b/core/res/res/values-it-masculine/strings.xml
index 823006b..7310eb8 100644
--- a/core/res/res/values-it-masculine/strings.xml
+++ b/core/res/res/values-it-masculine/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="relationTypeChild" msgid="9076258911292693601">"Figlio"</string>
<string name="relationTypeFriend" msgid="3192092625893980574">"Amico"</string>
<string name="relationTypeSpouse" msgid="6916682664436031703">"Marito"</string>
</resources>
diff --git a/core/res/res/values-it-neuter/strings.xml b/core/res/res/values-it-neuter/strings.xml
index d5ec313..ce433d7 100644
--- a/core/res/res/values-it-neuter/strings.xml
+++ b/core/res/res/values-it-neuter/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="relationTypeChild" msgid="9076258911292693601">"Figliə"</string>
<string name="relationTypeFriend" msgid="3192092625893980574">"Amicə"</string>
<string name="relationTypeSpouse" msgid="6916682664436031703">"Coniuge"</string>
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 355a0e9..76e4e83 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1275,7 +1275,7 @@
<string name="unsupported_display_size_show" msgid="980129850974919375">"להציג תמיד"</string>
<string name="unsupported_compile_sdk_message" msgid="7326293500707890537">"<xliff:g id="APP_NAME">%1$s</xliff:g> נבנתה לגרסה לא תואמת של מערכת ההפעלה של Android ועלולה להתנהג באופן לא צפוי. ייתכן שקיימת גרסה מעודכנת של האפליקציה."</string>
<string name="unsupported_compile_sdk_show" msgid="1601210057960312248">"להציג תמיד"</string>
- <string name="unsupported_compile_sdk_check_update" msgid="1103639989147664456">"האם יש עדכון חדש?"</string>
+ <string name="unsupported_compile_sdk_check_update" msgid="1103639989147664456">"יש עדכון חדש?"</string>
<string name="smv_application" msgid="3775183542777792638">"האפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> (תהליך <xliff:g id="PROCESS">%2$s</xliff:g>) הפרה את מדיניות StrictMode באכיפה עצמית שלה."</string>
<string name="smv_process" msgid="1398801497130695446">"התהליך <xliff:g id="PROCESS">%1$s</xliff:g> הפר את מדיניות StrictMode באכיפה עצמית."</string>
<string name="android_upgrading_title" product="default" msgid="7279077384220829683">"הטלפון מתעדכן…"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 5124c27..998c960 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1428,8 +1428,7 @@
<string name="share_remote_bugreport_action" msgid="7630880678785123682">"SHPËRNDAJ"</string>
<string name="decline_remote_bugreport_action" msgid="4040894777519784346">"REFUZO"</string>
<string name="select_input_method" msgid="3971267998568587025">"Zgjidh metodën e hyrjes"</string>
- <!-- no translation found for input_method_language_settings (8069089418056819437) -->
- <skip />
+ <string name="input_method_language_settings" msgid="8069089418056819437">"Cilësimet e gjuhës"</string>
<string name="show_ime" msgid="6406112007347443383">"Mbaje në ekran ndërsa tastiera fizike është aktive"</string>
<string name="hardware" msgid="3611039921284836033">"Përdor tastierën në ekran"</string>
<string name="select_keyboard_layout_notification_title" msgid="5823199895322205589">"Konfiguro <xliff:g id="DEVICE_NAME">%s</xliff:g>"</string>
diff --git a/core/res/res/values-watch/themes_device_defaults.xml b/core/res/res/values-watch/themes_device_defaults.xml
index 85d34e2..4d2085bb 100644
--- a/core/res/res/values-watch/themes_device_defaults.xml
+++ b/core/res/res/values-watch/themes_device_defaults.xml
@@ -548,4 +548,7 @@
<item name="primaryContentAlpha">@dimen/primary_content_alpha_device_default</item>
<item name="secondaryContentAlpha">@dimen/secondary_content_alpha_device_default</item>
</style>
+
+ <!-- Device default theme for the Input Method Switcher dialog. Override to make it dark. -->
+ <style name="Theme.DeviceDefault.InputMethodSwitcherDialog" parent="Theme.DeviceDefault.Dialog.Alert"/>
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 7cc9e13..440219d 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1078,6 +1078,11 @@
<!-- Background color to use for tooltip popups. -->
<attr name="tooltipBackgroundColor" format="reference|color" />
+ <attr name="tooltipCornerRadius" format="dimension" />
+ <attr name="tooltipHorizontalPadding" format="dimension" />
+ <attr name="tooltipVerticalPadding" format="dimension" />
+ <attr name="tooltipFontSize" format="dimension" />
+
<!-- Theme to use for Search Dialogs. -->
<attr name="searchDialogTheme" format="reference" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8ed444d..df288f9 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3065,10 +3065,13 @@
frameworks/base/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java -->
<integer name="config_userTypePackageWhitelistMode">13</integer> <!-- 1+4+8 -->
- <!-- Whether the main user is a permanent admin user. If the main user is a permanent admin user
- it can't be deleted or downgraded to non-admin status.
- This is generally only relevant on headless system user mode devices; on other devices, the
- main user is the system user which is always a permanent admin anyway. -->
+ <!-- Whether the device will automatically (at first boot) have a designated main user and treat
+ it as a permanent admin.
+ Since the main user is a permanent admin user it can't be deleted or downgraded to
+ non-admin status.
+ This is generally only relevant on headless system user mode (HSUM) devices; on other
+ devices, the main user is the system user which is always a permanent admin anyway.
+ Note that HSUM devices without this enabled will not automatically have a main user. -->
<bool name="config_isMainUserPermanentAdmin">true</bool>
<!-- Whether switch to headless system user is allowed. If allowed,
@@ -3079,7 +3082,7 @@
<bool name="config_enableMultiUserUI">false</bool>
<!-- Whether multiple admins are allowed on the device. If set to true, new users can be created
- with admin privileges and admin privileges can be granted/revoked from existing users. -->
+ with admin privileges and admin privileges can be granted/revoked from existing users. -->
<bool name="config_enableMultipleAdmins">false</bool>
<!-- Whether there is a communal profile which should always be running.
@@ -3961,6 +3964,9 @@
flag does not exist -->
<bool name="config_magnification_always_on_enabled">true</bool>
+ <!-- Whether to keep fullscreen magnification zoom level when context changes. -->
+ <bool name="config_magnification_keep_zoom_level_when_context_changed">false</bool>
+
<!-- If true, the display will be shifted around in ambient mode. -->
<bool name="config_enableBurnInProtection">false</bool>
@@ -6158,10 +6164,6 @@
is enabled and activity is connected to the camera in fullscreen. -->
<bool name="config_isWindowManagerCameraCompatSplitScreenAspectRatioEnabled">false</bool>
- <!-- Whether a camera compat controller is enabled to allow the user to apply or revert
- treatment for stretched issues in camera viewfinder. -->
- <bool name="config_isCameraCompatControlForStretchedIssuesEnabled">false</bool>
-
<!-- Docking is a uiMode configuration change and will cause activities to relaunch if it's not
handled. If true, the configuration change will be sent but activities will not be
relaunched upon docking. Apps with desk resources will behave like normal, since they may
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 6cba84b..77b5587 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -771,6 +771,7 @@
<dimen name="tooltip_precise_anchor_threshold">96dp</dimen>
<!-- Extra tooltip offset used when anchoring to the mouse/touch position -->
<dimen name="tooltip_precise_anchor_extra_offset">8dp</dimen>
+ <dimen name="tooltip_font_size">14sp</dimen>
<!-- The max amount of scroll ItemTouchHelper will trigger if dragged view is out of
RecyclerView's bounds.-->
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index 972fe7e..35f35fb 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -204,4 +204,9 @@
<dimen name="progress_bar_size_small">16dip</dimen>
<dimen name="progress_bar_size_medium">48dp</dimen>
<dimen name="progress_bar_size_large">76dp</dimen>
+
+ <dimen name="tooltip_corner_radius_material">4dp</dimen>
+ <dimen name="tooltip_horizontal_padding_material">8dp</dimen>
+ <dimen name="tooltip_vertical_padding_material">4dp</dimen>
+ <dimen name="tooltip_font_size_material">12sp</dimen>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e94db2d..9104379 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -6496,10 +6496,14 @@
<string name="screen_not_shared_sensitive_content">App content hidden from screen share for security</string>
<!-- Satellite related messages -->
- <!-- Notification title when satellite service is connected. -->
+ <!-- Notification title when satellite service is auto connected. -->
<string name="satellite_notification_title">Auto connected to satellite</string>
- <!-- Notification summary when satellite service is connected. [CHAR LIMIT=NONE] -->
+ <!-- Notification summary when satellite service is auto connected. [CHAR LIMIT=NONE] -->
<string name="satellite_notification_summary">You can send and receive messages without a mobile or Wi-Fi network</string>
+ <!-- Notification title when satellite service can be manually enabled. -->
+ <string name="satellite_notification_manual_title">Use satellite messaging?</string>
+ <!-- Notification summary when satellite service can be manually enabled. [CHAR LIMIT=NONE] -->
+ <string name="satellite_notification_manual_summary">Send and receive messages without a mobile or Wi-Fi network</string>
<!-- Invoke "What to expect" dialog of messaging application -->
<string name="satellite_notification_open_message">Open Messages</string>
<!-- Invoke Satellite setting activity of Settings -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index aabc8ca..c084b4c 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -998,7 +998,7 @@
<style name="TextAppearance.Tooltip">
<item name="fontFamily">sans-serif</item>
- <item name="textSize">14sp</item>
+ <item name="textSize">?android:attr/tooltipFontSize</item>
</style>
<style name="Widget.ActivityChooserView">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index cbf3fe7..8f4018f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4767,7 +4767,6 @@
<java-symbol type="bool" name="config_isCompatFakeFocusEnabled" />
<java-symbol type="bool" name="config_isWindowManagerCameraCompatTreatmentEnabled" />
<java-symbol type="bool" name="config_isWindowManagerCameraCompatSplitScreenAspectRatioEnabled" />
- <java-symbol type="bool" name="config_isCameraCompatControlForStretchedIssuesEnabled" />
<java-symbol type="bool" name="config_skipActivityRelaunchWhenDocking" />
<java-symbol type="bool" name="config_hideDisplayCutoutWithDisplayArea" />
@@ -4780,6 +4779,7 @@
<java-symbol type="bool" name="config_magnification_area" />
<java-symbol type="bool" name="config_magnification_always_on_enabled" />
+ <java-symbol type="bool" name="config_magnification_keep_zoom_level_when_context_changed" />
<java-symbol type="bool" name="config_trackerAppNeedsPermissions"/>
<!-- FullScreenMagnification thumbnail -->
@@ -5500,6 +5500,8 @@
<!-- System notification for satellite service -->
<java-symbol type="string" name="satellite_notification_title" />
<java-symbol type="string" name="satellite_notification_summary" />
+ <java-symbol type="string" name="satellite_notification_manual_title" />
+ <java-symbol type="string" name="satellite_notification_manual_summary" />
<java-symbol type="string" name="satellite_notification_open_message" />
<java-symbol type="string" name="satellite_notification_how_it_works" />
<java-symbol type="drawable" name="ic_satellite_alt_24px" />
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index c3d304d..3b3bb8d 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -461,6 +461,10 @@
<item name="tooltipFrameBackground">@drawable/tooltip_frame</item>
<item name="tooltipForegroundColor">@color/bright_foreground_light</item>
<item name="tooltipBackgroundColor">@color/tooltip_background_light</item>
+ <item name="tooltipCornerRadius">@dimen/tooltip_corner_radius</item>
+ <item name="tooltipHorizontalPadding">@dimen/tooltip_horizontal_padding</item>
+ <item name="tooltipVerticalPadding">@dimen/tooltip_vertical_padding</item>
+ <item name="tooltipFontSize">@dimen/tooltip_font_size</item>
<!-- Autofill: max width/height of the dataset picker as a fraction of screen size -->
<item name="autofillDatasetPickerMaxWidth">@dimen/autofill_dataset_picker_max_width</item>
@@ -582,9 +586,10 @@
<item name="floatingToolbarOpenDrawable">@drawable/ic_menu_moreoverflow_material_light</item>
<item name="floatingToolbarDividerColor">@color/floating_popup_divider_light</item>
- <!-- Tooltip popup colors -->
+ <!-- Tooltip popup styles -->
<item name="tooltipForegroundColor">@color/bright_foreground_dark</item>
<item name="tooltipBackgroundColor">@color/tooltip_background_dark</item>
+
</style>
<!-- Variant of {@link #Theme_Light} with no title bar -->
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 8e2fb34..9f11208 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -408,8 +408,12 @@
<item name="colorProgressBackgroundNormal">?attr/colorControlNormal</item>
<!-- Tooltip popup properties -->
- <item name="tooltipForegroundColor">@color/foreground_material_light</item>
- <item name="tooltipBackgroundColor">@color/tooltip_background_light</item>
+ <item name="tooltipForegroundColor">@color/system_on_surface_light</item>
+ <item name="tooltipBackgroundColor">@color/system_surface_light</item>
+ <item name="tooltipCornerRadius">@dimen/tooltip_corner_radius_material</item>
+ <item name="tooltipHorizontalPadding">@dimen/tooltip_horizontal_padding_material</item>
+ <item name="tooltipVerticalPadding">@dimen/tooltip_vertical_padding_material</item>
+ <item name="tooltipFontSize">@dimen/tooltip_font_size_material</item>
</style>
<!-- Material theme (light version). -->
@@ -785,8 +789,13 @@
<item name="colorProgressBackgroundNormal">?attr/colorControlNormal</item>
<!-- Tooltip popup properties -->
- <item name="tooltipForegroundColor">@color/foreground_material_dark</item>
- <item name="tooltipBackgroundColor">@color/tooltip_background_dark</item>
+ <item name="tooltipForegroundColor">@color/system_on_surface_dark</item>
+ <item name="tooltipBackgroundColor">@color/system_surface_dark</item>
+ <item name="tooltipCornerRadius">@dimen/tooltip_corner_radius_material</item>
+ <item name="tooltipHorizontalPadding">@dimen/tooltip_horizontal_padding_material</item>
+ <item name="tooltipVerticalPadding">@dimen/tooltip_vertical_padding_material</item>
+ <item name="tooltipFontSize">@dimen/tooltip_font_size_material</item>
+
</style>
<!-- Variant of the material (light) theme that has a solid (opaque) action bar
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 41696df..5793bbe 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -284,3 +284,510 @@
],
auto_gen_config: true,
}
+
+FLAKY_OR_IGNORED = [
+ "androidx.test.filters.FlakyTest",
+ "org.junit.Ignore",
+]
+
+test_module_config {
+ name: "FrameworksCoreTests_Presubmit",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+ exclude_annotations: FLAKY_OR_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_inputmethod",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: [
+ "com.android.internal.inputmethod",
+ "android.view.inputmethod",
+ ],
+ exclude_annotations: ["androidx.test.filters.FlakyTest"],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_context",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["android.content.ContextTest"],
+ exclude_annotations: FLAKY_OR_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_keyguard_manager",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["android.app.KeyguardManagerTest"],
+ exclude_annotations: FLAKY_OR_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_property_invalidated_cache",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["android.app.PropertyInvalidatedCacheTests"],
+ exclude_annotations: FLAKY_OR_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_android_content",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: [
+ "android.content.ContextTest",
+ "android.content.ComponentCallbacksControllerTest",
+ "android.content.ContextWrapperTest",
+ ],
+ exclude_annotations: FLAKY_OR_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_sqlite",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["android.database.sqlite.SQLiteRawStatementTest"],
+ exclude_annotations: FLAKY_OR_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_android_net",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["android.net"],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+ exclude_annotations: FLAKY_OR_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_battery_stats",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["com.android.internal.os.BatteryStatsTests"],
+ exclude_annotations: ["com.android.internal.os.SkipPresubmit"],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_environment",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["android.os.EnvironmentTest"],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_util_data_charset",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: [
+ "com.android.internal.util.FastDataTest",
+ "android.util.CharsetUtilsTest",
+ ],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_xml",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: [
+ "android.util.XmlTest",
+ "android.util.BinaryXmlTest",
+ ],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_util_apk",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["android.util.apk.SourceStampVerifierTest"],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_textclassifier",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["android.view.textclassifier"],
+ exclude_annotations: ["androidx.test.filters.FlakyTest"],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_internal_app",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["com.android.internal.app."],
+ exclude_filters: [
+ "com.android.internal.app.WindowDecorActionBarTest",
+ "com.android.internal.app.IntentForwarderActivityTest",
+ ],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_internal_content",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["com.android.internal.content."],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_internal_infra",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["com.android.internal.infra."],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_internal_jank",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["com.android.internal.jank"],
+ exclude_annotations: FLAKY_OR_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_internal_os_binder",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["com.android.internal.os.BinderDeathDispatcherTest"],
+ exclude_annotations: ["com.android.internal.os.SkipPresubmit"],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_internal_os_kernel",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: [
+ "com.android.internal.os.KernelCpuUidClusterTimeReaderTest",
+ "com.android.internal.os.KernelCpuUidBpfMapReaderTest",
+ "com.android.internal.os.KernelCpuUidActiveTimeReaderTest",
+ "com.android.internal.os.KernelCpuUidFreqTimeReaderTest",
+ "com.android.internal.os.KernelSingleUidTimeReaderTest",
+ ],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_server_power",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["com.android.server.power.stats.BstatsCpuTimesValidationTest"],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_internal_security",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["com.android.internal.security."],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_internal_util_latency_tracker",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["com.android.internal.util.LatencyTrackerTest"],
+ exclude_annotations: FLAKY_OR_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_content_capture_options",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["android.content.ContentCaptureOptionsTest"],
+ exclude_annotations: FLAKY_OR_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_android_content_integrity",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["android.content.integrity."],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_android_content_pm_PreSubmit",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["android.content.pm."],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+ exclude_annotations: FLAKY_OR_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_android_content_pm_PostSubmit",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["android.content.pm."],
+ include_annotations: ["android.platform.test.annotations.Postsubmit"],
+ exclude_annotations: FLAKY_OR_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_android_content_res",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["android.content.res."],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+ exclude_annotations: [
+ "androidx.test.filters.FlakyTest",
+ "android.platform.test.annotations.Postsubmit",
+ "org.junit.Ignore",
+ ],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_android_content_res_PostSubmit",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["android.content.res."],
+ include_annotations: ["android.platform.test.annotations.Postsubmit"],
+ exclude_annotations: FLAKY_OR_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_android_service",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: [
+ "android.service.euicc",
+ "android.service.notification",
+ "android.service.quicksettings",
+ "android.service.settings.suggestions",
+ "android.service.controls.templates",
+ "android.service.controls.actions",
+ "android.service.controls",
+ ],
+ exclude_annotations: ["org.junit.Ignore"],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_android_view_contentcapture",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["android.view.contentcapture"],
+ exclude_annotations: FLAKY_OR_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_android_view_contentprotection",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["android.view.contentprotection"],
+ exclude_annotations: FLAKY_OR_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_com_android_internal_content_Presubmit",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["com.android.internal.content."],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+ exclude_annotations: FLAKY_OR_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_drawable",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["android.graphics.drawable.IconTest"],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_accessibility_NO_FLAKES",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: [
+ "com.android.internal.accessibility",
+ "android.accessibilityservice",
+ "android.view.accessibility",
+ ],
+ exclude_annotations: ["androidx.test.filters.FlakyTest"],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_accessibility",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: [
+ "com.android.internal.accessibility",
+ "android.accessibilityservice",
+ "android.view.accessibility",
+ ],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_usage",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["android.app.usage"],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_fastdata",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["com.android.internal.util.FastDataTest"],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_hardware_input",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: ["android.hardware.input"],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_view_verified",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: [
+ "android.view.VerifiedMotionEventTest",
+ "android.view.VerifiedKeyEventTest",
+ ],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_jank",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_filters: [
+ "com.android.internal.jank.FrameTrackerTest",
+ "com.android.internal.jank.InteractionJankMonitorTest",
+ "com.android.internal.util.LatencyTrackerTest",
+ ],
+ exclude_annotations: FLAKY_OR_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_Platinum",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "device-tests",
+ "device-platinum-tests",
+ ],
+ include_annotations: ["android.platform.test.annotations.PlatinumTest"],
+ exclude_annotations: FLAKY_OR_IGNORED,
+}
diff --git a/core/tests/coretests/src/android/app/ActivityManagerTest.java b/core/tests/coretests/src/android/app/ActivityManagerTest.java
index 3c042ba..d850f86 100644
--- a/core/tests/coretests/src/android/app/ActivityManagerTest.java
+++ b/core/tests/coretests/src/android/app/ActivityManagerTest.java
@@ -26,7 +26,7 @@
import android.os.UserHandle;
import android.platform.test.ravenwood.RavenwoodRule;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Rule;
import org.junit.Test;
diff --git a/core/tests/coretests/src/android/app/ApplicationErrorReportTest.java b/core/tests/coretests/src/android/app/ApplicationErrorReportTest.java
index 8dc5ad6..c4240a2 100644
--- a/core/tests/coretests/src/android/app/ApplicationErrorReportTest.java
+++ b/core/tests/coretests/src/android/app/ApplicationErrorReportTest.java
@@ -21,8 +21,8 @@
import android.app.ApplicationErrorReport.CrashInfo;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/app/ApplicationLoadersTest.java b/core/tests/coretests/src/android/app/ApplicationLoadersTest.java
index 565e21d..dfb8a23 100644
--- a/core/tests/coretests/src/android/app/ApplicationLoadersTest.java
+++ b/core/tests/coretests/src/android/app/ApplicationLoadersTest.java
@@ -22,8 +22,8 @@
import android.content.pm.SharedLibraryInfo;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.google.android.collect.Lists;
diff --git a/core/tests/coretests/src/android/app/BackgroundStartPrivilegesTest.java b/core/tests/coretests/src/android/app/BackgroundStartPrivilegesTest.java
index 982ad63..cf6266c 100644
--- a/core/tests/coretests/src/android/app/BackgroundStartPrivilegesTest.java
+++ b/core/tests/coretests/src/android/app/BackgroundStartPrivilegesTest.java
@@ -26,8 +26,8 @@
import android.os.Binder;
import android.os.IBinder;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/app/LoaderLifecycleTest.java b/core/tests/coretests/src/android/app/LoaderLifecycleTest.java
index e343383..2eb0bbe 100644
--- a/core/tests/coretests/src/android/app/LoaderLifecycleTest.java
+++ b/core/tests/coretests/src/android/app/LoaderLifecycleTest.java
@@ -28,9 +28,9 @@
import android.os.Parcelable;
import android.util.ArrayMap;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.MediumTest;
import androidx.test.rule.ActivityTestRule;
-import androidx.test.runner.AndroidJUnit4;
import org.junit.Rule;
import org.junit.Test;
diff --git a/core/tests/coretests/src/android/app/NotificationChannelGroupTest.java b/core/tests/coretests/src/android/app/NotificationChannelGroupTest.java
index 046f5ac..322893c 100644
--- a/core/tests/coretests/src/android/app/NotificationChannelGroupTest.java
+++ b/core/tests/coretests/src/android/app/NotificationChannelGroupTest.java
@@ -23,8 +23,8 @@
import android.platform.test.annotations.Presubmit;
import android.text.TextUtils;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.google.common.base.Strings;
diff --git a/core/tests/coretests/src/android/app/NotificationChannelTest.java b/core/tests/coretests/src/android/app/NotificationChannelTest.java
index 504f98f..c08e42b 100644
--- a/core/tests/coretests/src/android/app/NotificationChannelTest.java
+++ b/core/tests/coretests/src/android/app/NotificationChannelTest.java
@@ -23,7 +23,6 @@
import static junit.framework.TestCase.assertNull;
import static junit.framework.TestCase.assertTrue;
-import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
@@ -31,7 +30,6 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-import android.annotation.FlaggedApi;
import android.content.AttributionSource;
import android.content.ContentProvider;
import android.content.ContentResolver;
@@ -54,8 +52,8 @@
import android.test.mock.MockContentResolver;
import android.util.Xml;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
diff --git a/core/tests/coretests/src/android/app/NotificationHistoryTest.java b/core/tests/coretests/src/android/app/NotificationHistoryTest.java
index c44c1eb..38581e8 100644
--- a/core/tests/coretests/src/android/app/NotificationHistoryTest.java
+++ b/core/tests/coretests/src/android/app/NotificationHistoryTest.java
@@ -24,7 +24,7 @@
import android.platform.test.annotations.Presubmit;
import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java b/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java
index cd6abdd..b5ee130 100644
--- a/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java
+++ b/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java
@@ -375,20 +375,4 @@
PropertyInvalidatedCache.MODULE_BLUETOOTH, "getState");
assertEquals(n1, "cache_key.bluetooth.get_state");
}
-
- @Test
- public void testOnTrimMemory() {
- TestCache cache = new TestCache(MODULE, "trimMemoryTest");
- // The cache is not active until it has been invalidated once.
- cache.invalidateCache();
- // Populate the cache with six entries.
- for (int i = 0; i < 6; i++) {
- cache.query(i);
- }
- // The maximum number of entries in TestCache is 4, so even though six entries were
- // created, only four are retained.
- assertEquals(4, cache.size());
- PropertyInvalidatedCache.onTrimMemory();
- assertEquals(0, cache.size());
- }
}
diff --git a/core/tests/coretests/src/android/app/QueuedWorkTest.java b/core/tests/coretests/src/android/app/QueuedWorkTest.java
index 7021187..230c9e8 100644
--- a/core/tests/coretests/src/android/app/QueuedWorkTest.java
+++ b/core/tests/coretests/src/android/app/QueuedWorkTest.java
@@ -20,18 +20,18 @@
import android.platform.test.annotations.Presubmit;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.Semaphore;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
@RunWith(AndroidJUnit4.class)
@Presubmit
@SmallTest
diff --git a/core/tests/coretests/src/android/app/activity/ActivityTransitionDrawableTest.java b/core/tests/coretests/src/android/app/activity/ActivityTransitionDrawableTest.java
index 2c4e443..a50f524 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityTransitionDrawableTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityTransitionDrawableTest.java
@@ -27,9 +27,9 @@
import android.view.View;
import android.view.Window;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.MediumTest;
import androidx.test.rule.ActivityTestRule;
-import androidx.test.runner.AndroidJUnit4;
import org.junit.Rule;
import org.junit.Test;
diff --git a/core/tests/coretests/src/android/app/activity/RegisterComponentCallbacksTest.java b/core/tests/coretests/src/android/app/activity/RegisterComponentCallbacksTest.java
index fd1add9..5958d15 100644
--- a/core/tests/coretests/src/android/app/activity/RegisterComponentCallbacksTest.java
+++ b/core/tests/coretests/src/android/app/activity/RegisterComponentCallbacksTest.java
@@ -36,8 +36,8 @@
import androidx.test.core.app.ActivityScenario;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import org.junit.Rule;
import org.junit.Test;
diff --git a/core/tests/coretests/src/android/app/admin/PackagePolicyTest.java b/core/tests/coretests/src/android/app/admin/PackagePolicyTest.java
index d8298fd..c648fd2 100644
--- a/core/tests/coretests/src/android/app/admin/PackagePolicyTest.java
+++ b/core/tests/coretests/src/android/app/admin/PackagePolicyTest.java
@@ -29,8 +29,8 @@
import android.platform.test.annotations.Presubmit;
import android.util.ArraySet;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/app/admin/PasswordPolicyTest.java b/core/tests/coretests/src/android/app/admin/PasswordPolicyTest.java
index f1be173..2d0dd9f 100644
--- a/core/tests/coretests/src/android/app/admin/PasswordPolicyTest.java
+++ b/core/tests/coretests/src/android/app/admin/PasswordPolicyTest.java
@@ -36,8 +36,8 @@
import android.app.admin.PasswordPolicy;
import android.platform.test.annotations.Presubmit;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/app/assist/AssistStructureTest.java b/core/tests/coretests/src/android/app/assist/AssistStructureTest.java
index 1f2788c..a28b2f6 100644
--- a/core/tests/coretests/src/android/app/assist/AssistStructureTest.java
+++ b/core/tests/coretests/src/android/app/assist/AssistStructureTest.java
@@ -49,8 +49,8 @@
import androidx.annotation.NonNull;
import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.rule.ActivityTestRule;
-import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
diff --git a/core/tests/coretests/src/android/app/backup/BackupAgentTest.java b/core/tests/coretests/src/android/app/backup/BackupAgentTest.java
index cd5deb6..93bbb3a 100644
--- a/core/tests/coretests/src/android/app/backup/BackupAgentTest.java
+++ b/core/tests/coretests/src/android/app/backup/BackupAgentTest.java
@@ -32,7 +32,7 @@
import android.platform.test.flag.junit.SetFlagsRule;
import android.util.ArraySet;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.server.backup.Flags;
diff --git a/core/tests/coretests/src/android/app/backup/BackupManagerMonitorWrapperTest.java b/core/tests/coretests/src/android/app/backup/BackupManagerMonitorWrapperTest.java
index 1f5e0cf..3620a0c 100644
--- a/core/tests/coretests/src/android/app/backup/BackupManagerMonitorWrapperTest.java
+++ b/core/tests/coretests/src/android/app/backup/BackupManagerMonitorWrapperTest.java
@@ -25,7 +25,7 @@
import android.os.Bundle;
import android.platform.test.annotations.Presubmit;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
diff --git a/core/tests/coretests/src/android/app/backup/BackupManagerTest.java b/core/tests/coretests/src/android/app/backup/BackupManagerTest.java
index 567ca01..88994c9 100644
--- a/core/tests/coretests/src/android/app/backup/BackupManagerTest.java
+++ b/core/tests/coretests/src/android/app/backup/BackupManagerTest.java
@@ -30,7 +30,7 @@
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
diff --git a/core/tests/coretests/src/android/app/backup/BackupRestoreEventLoggerTest.java b/core/tests/coretests/src/android/app/backup/BackupRestoreEventLoggerTest.java
index 0aefef2..7b41217 100644
--- a/core/tests/coretests/src/android/app/backup/BackupRestoreEventLoggerTest.java
+++ b/core/tests/coretests/src/android/app/backup/BackupRestoreEventLoggerTest.java
@@ -28,7 +28,7 @@
import android.platform.test.annotations.Presubmit;
import android.platform.test.flag.junit.SetFlagsRule;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.server.backup.Flags;
diff --git a/core/tests/coretests/src/android/app/compat/CompatChangesTest.java b/core/tests/coretests/src/android/app/compat/CompatChangesTest.java
index fbd02ed..8fd21c8 100644
--- a/core/tests/coretests/src/android/app/compat/CompatChangesTest.java
+++ b/core/tests/coretests/src/android/app/compat/CompatChangesTest.java
@@ -25,8 +25,8 @@
import android.platform.test.annotations.Presubmit;
import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
diff --git a/core/tests/coretests/src/android/app/people/PeopleManagerTest.java b/core/tests/coretests/src/android/app/people/PeopleManagerTest.java
index a2afc77..1296d32 100644
--- a/core/tests/coretests/src/android/app/people/PeopleManagerTest.java
+++ b/core/tests/coretests/src/android/app/people/PeopleManagerTest.java
@@ -31,7 +31,7 @@
import android.util.Pair;
import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
diff --git a/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java b/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java
index 5cee2c1..a9d1d35 100644
--- a/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java
+++ b/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java
@@ -43,8 +43,8 @@
import android.os.UserHandle;
import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.google.common.collect.ImmutableList;
diff --git a/core/tests/coretests/src/android/app/usage/EventListTest.java b/core/tests/coretests/src/android/app/usage/EventListTest.java
index 685fcae..d5a6858 100644
--- a/core/tests/coretests/src/android/app/usage/EventListTest.java
+++ b/core/tests/coretests/src/android/app/usage/EventListTest.java
@@ -22,8 +22,8 @@
import android.util.Log;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/app/usage/ParcelableUsageEventListTest.java b/core/tests/coretests/src/android/app/usage/ParcelableUsageEventListTest.java
index da40f2a..1c35a64 100644
--- a/core/tests/coretests/src/android/app/usage/ParcelableUsageEventListTest.java
+++ b/core/tests/coretests/src/android/app/usage/ParcelableUsageEventListTest.java
@@ -30,8 +30,8 @@
import android.os.Parcel;
import android.os.PersistableBundle;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
-import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/app/usage/UsageEventsQueryTest.java b/core/tests/coretests/src/android/app/usage/UsageEventsQueryTest.java
index 5516845..97d2819 100644
--- a/core/tests/coretests/src/android/app/usage/UsageEventsQueryTest.java
+++ b/core/tests/coretests/src/android/app/usage/UsageEventsQueryTest.java
@@ -25,8 +25,8 @@
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import org.junit.Rule;
import org.junit.Test;
diff --git a/core/tests/coretests/src/android/app/usage/UsageStatsPersistenceTest.java b/core/tests/coretests/src/android/app/usage/UsageStatsPersistenceTest.java
index 3618543..ad6b1b8 100644
--- a/core/tests/coretests/src/android/app/usage/UsageStatsPersistenceTest.java
+++ b/core/tests/coretests/src/android/app/usage/UsageStatsPersistenceTest.java
@@ -18,8 +18,8 @@
import static junit.framework.Assert.fail;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.internal.util.ArrayUtils;
diff --git a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
index f728080..69a7a68 100644
--- a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
+++ b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
@@ -38,8 +38,8 @@
import android.os.UserHandle;
import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.UiDevice;
import org.junit.Before;
diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java
index bd9c4b8..519f23b 100644
--- a/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java
+++ b/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java
@@ -28,6 +28,7 @@
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.util.Printer;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -43,10 +44,13 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
@RunWith(AndroidJUnit4.class)
@SmallTest
@@ -400,4 +404,138 @@
}
assertFalse(allowed);
}
+
+ /** Dumpsys information about a single database. */
+
+ /**
+ * Collect and parse dumpsys output. This is not a full parser. It is only enough to support
+ * the unit tests.
+ */
+ private static class Dumpsys {
+ // Regular expressions for parsing the output. Reportedly, regular expressions are
+ // expensive, so these are created only if a dumpsys object is created.
+ private static final Object sLock = new Object();
+ static Pattern mPool;
+ static Pattern mConnection;
+ static Pattern mEntry;
+ static Pattern mSingleWord;
+ static Pattern mNone;
+
+ // The raw strings read from dumpsys. Once loaded, this list never changes.
+ final ArrayList<String> mRaw = new ArrayList<>();
+
+ // Parsed dumpsys. This contains only the bits that are being tested.
+ static class Connection {
+ ArrayList<String> mRecent = new ArrayList<>();
+ ArrayList<String> mLong = new ArrayList<>();
+ }
+ static class Database {
+ String mPath;
+ ArrayList<Connection> mConnection = new ArrayList<>();
+ }
+ ArrayList<Database> mDatabase;
+ ArrayList<String> mConcurrent;
+
+ Dumpsys() {
+ SQLiteDebug.dump(
+ new Printer() { public void println(String x) { mRaw.add(x); } },
+ new String[0]);
+ parse();
+ }
+
+ /** Parse the raw text. Return true if no errors were detected. */
+ boolean parse() {
+ initialize();
+
+ // Reset the parsed information. This method may be called repeatedly.
+ mDatabase = new ArrayList<>();
+ mConcurrent = new ArrayList<>();
+
+ Database current = null;
+ Connection connection = null;
+ Matcher matcher;
+ for (int i = 0; i < mRaw.size(); i++) {
+ final String line = mRaw.get(i);
+ matcher = mPool.matcher(line);
+ if (matcher.lookingAt()) {
+ current = new Database();
+ mDatabase.add(current);
+ current.mPath = matcher.group(1);
+ continue;
+ }
+ matcher = mConnection.matcher(line);
+ if (matcher.lookingAt()) {
+ connection = new Connection();
+ current.mConnection.add(connection);
+ continue;
+ }
+
+ if (line.contains("Most recently executed operations")) {
+ i += readTable(connection.mRecent, i, mEntry);
+ continue;
+ }
+
+ if (line.contains("Operations exceeding 2000ms")) {
+ i += readTable(connection.mLong, i, mEntry);
+ continue;
+ }
+ if (line.contains("Concurrently opened database files")) {
+ i += readTable(mConcurrent, i, mSingleWord);
+ continue;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Read a series of lines following a header. Return the number of lines read. The input
+ * line number is the number of the header.
+ */
+ private int readTable(List<String> s, int header, Pattern p) {
+ // Special case: if the first line is "<none>" then there are no more lines to the
+ // table.
+ if (lookingAt(header+1, mNone)) return 1;
+
+ int i;
+ for (i = header + 1; i < mRaw.size() && lookingAt(i, p); i++) {
+ s.add(mRaw.get(i).trim());
+ }
+ return i - header;
+ }
+
+ /** Return true if the n'th raw line matches the pattern. */
+ boolean lookingAt(int n, Pattern p) {
+ return p.matcher(mRaw.get(n)).lookingAt();
+ }
+
+ /** Compile the regular expressions the first time. */
+ private static void initialize() {
+ synchronized (sLock) {
+ if (mPool != null) return;
+ mPool = Pattern.compile("Connection pool for (\\S+):");
+ mConnection = Pattern.compile("\\s+Connection #(\\d+):");
+ mEntry = Pattern.compile("\\s+(\\d+): ");
+ mSingleWord = Pattern.compile(" (\\S+)$");
+ mNone = Pattern.compile("\\s+<none>$");
+ }
+ }
+ }
+
+ @Test
+ public void testDumpsys() throws Exception {
+ Dumpsys dumpsys = new Dumpsys();
+
+ assertEquals(1, dumpsys.mDatabase.size());
+ // Note: cannot test mConcurrent because that attribute is not hermitic with respect to
+ // the tests.
+
+ Dumpsys.Database db = dumpsys.mDatabase.get(0);
+
+ // Work with normalized paths.
+ String wantPath = mDatabaseFile.toPath().toRealPath().toString();
+ String realPath = new File(db.mPath).toPath().toRealPath().toString();
+ assertEquals(wantPath, realPath);
+
+ assertEquals(1, db.mConnection.size());
+ }
}
diff --git a/core/tests/coretests/src/android/hardware/biometrics/BiometricPromptTest.java b/core/tests/coretests/src/android/hardware/biometrics/BiometricPromptTest.java
index 5464ea3..d6c0e99 100644
--- a/core/tests/coretests/src/android/hardware/biometrics/BiometricPromptTest.java
+++ b/core/tests/coretests/src/android/hardware/biometrics/BiometricPromptTest.java
@@ -16,7 +16,6 @@
package android.hardware.biometrics;
-import static android.hardware.biometrics.BiometricPrompt.MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER;
import static android.hardware.biometrics.PromptContentViewWithMoreOptionsButton.MAX_DESCRIPTION_CHARACTER_NUMBER;
import static android.hardware.biometrics.PromptVerticalListContentView.MAX_EACH_ITEM_CHARACTER_NUMBER;
import static android.hardware.biometrics.PromptVerticalListContentView.MAX_ITEM_NUMBER;
@@ -117,19 +116,7 @@
() -> new BiometricPrompt.Builder(mContext).setLogoDescription(null)
);
- assertThat(e).hasMessageThat().contains(
- "Logo description passed in can not be null or exceed");
- }
-
- @Test
- public void testLogoDescription_charLimit() {
- IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
- () -> new BiometricPrompt.Builder(mContext).setLogoDescription(
- generateRandomString(MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER + 1))
- );
-
- assertThat(e).hasMessageThat().contains(
- "Logo description passed in can not be null or exceed");
+ assertThat(e).hasMessageThat().isEqualTo("Logo description passed in can not be null");
}
@Test
diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java
index 66b22a8..774878a 100644
--- a/core/tests/coretests/src/android/os/FileUtilsTest.java
+++ b/core/tests/coretests/src/android/os/FileUtilsTest.java
@@ -54,7 +54,7 @@
import static org.junit.Assert.fail;
import android.os.FileUtils.MemoryPipe;
-import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.annotations.DisabledOnRavenwood;
import android.platform.test.ravenwood.RavenwoodRule;
import android.provider.DocumentsContract.Document;
import android.system.Os;
@@ -156,7 +156,7 @@
}
@Test
- @IgnoreUnderRavenwood(blockedBy = MemoryPipe.class)
+ @DisabledOnRavenwood(blockedBy = MemoryPipe.class)
public void testCopy_FileToPipe() throws Exception {
for (int size : DATA_SIZES) {
final File src = new File(mTarget, "src");
@@ -177,7 +177,7 @@
}
@Test
- @IgnoreUnderRavenwood(blockedBy = MemoryPipe.class)
+ @DisabledOnRavenwood(blockedBy = MemoryPipe.class)
public void testCopy_PipeToFile() throws Exception {
for (int size : DATA_SIZES) {
final File dest = new File(mTarget, "dest");
@@ -197,7 +197,7 @@
}
@Test
- @IgnoreUnderRavenwood(blockedBy = MemoryPipe.class)
+ @DisabledOnRavenwood(blockedBy = MemoryPipe.class)
public void testCopy_PipeToPipe() throws Exception {
for (int size : DATA_SIZES) {
byte[] expected = new byte[size];
@@ -215,7 +215,7 @@
}
@Test
- @IgnoreUnderRavenwood(blockedBy = MemoryPipe.class)
+ @DisabledOnRavenwood(blockedBy = MemoryPipe.class)
public void testCopy_ShortPipeToFile() throws Exception {
byte[] source = new byte[33_000_000];
new Random().nextBytes(source);
@@ -257,9 +257,9 @@
assertArrayEquals(expected, actual);
}
- //TODO(ravenwood) Remove the _$noRavenwood suffix and add @RavenwoodIgnore instead
@Test
- public void testCopy_SocketToFile_FileToSocket$noRavenwood() throws Exception {
+ @DisabledOnRavenwood(reason = "Missing Os methods in Ravenwood")
+ public void testCopy_SocketToFile_FileToSocket() throws Exception {
for (int size : DATA_SIZES ) {
final File src = new File(mTarget, "src");
final File dest = new File(mTarget, "dest");
@@ -510,7 +510,7 @@
}
@Test
- @IgnoreUnderRavenwood(blockedBy = android.webkit.MimeTypeMap.class)
+ @DisabledOnRavenwood(blockedBy = android.webkit.MimeTypeMap.class)
public void testBuildUniqueFile_normal() throws Exception {
assertNameEquals("test.jpg", FileUtils.buildUniqueFile(mTarget, "image/jpeg", "test"));
assertNameEquals("test.jpg", FileUtils.buildUniqueFile(mTarget, "image/jpeg", "test.jpg"));
@@ -530,7 +530,7 @@
}
@Test
- @IgnoreUnderRavenwood(blockedBy = android.webkit.MimeTypeMap.class)
+ @DisabledOnRavenwood(blockedBy = android.webkit.MimeTypeMap.class)
public void testBuildUniqueFile_unknown() throws Exception {
assertNameEquals("test",
FileUtils.buildUniqueFile(mTarget, "application/octet-stream", "test"));
@@ -544,7 +544,7 @@
}
@Test
- @IgnoreUnderRavenwood(blockedBy = android.webkit.MimeTypeMap.class)
+ @DisabledOnRavenwood(blockedBy = android.webkit.MimeTypeMap.class)
public void testBuildUniqueFile_dir() throws Exception {
assertNameEquals("test", FileUtils.buildUniqueFile(mTarget, Document.MIME_TYPE_DIR, "test"));
new File(mTarget, "test").mkdir();
@@ -559,7 +559,7 @@
}
@Test
- @IgnoreUnderRavenwood(blockedBy = android.webkit.MimeTypeMap.class)
+ @DisabledOnRavenwood(blockedBy = android.webkit.MimeTypeMap.class)
public void testBuildUniqueFile_increment() throws Exception {
assertNameEquals("test.jpg", FileUtils.buildUniqueFile(mTarget, "image/jpeg", "test.jpg"));
new File(mTarget, "test.jpg").createNewFile();
@@ -579,7 +579,7 @@
}
@Test
- @IgnoreUnderRavenwood(blockedBy = android.webkit.MimeTypeMap.class)
+ @DisabledOnRavenwood(blockedBy = android.webkit.MimeTypeMap.class)
public void testBuildUniqueFile_mimeless() throws Exception {
assertNameEquals("test.jpg", FileUtils.buildUniqueFile(mTarget, "test.jpg"));
new File(mTarget, "test.jpg").createNewFile();
@@ -675,8 +675,7 @@
}
@Test
- @IgnoreUnderRavenwood(reason = "Requires kernel support")
- public void testTranslateMode() throws Exception {
+ public void testTranslateMode() {
assertTranslate("r", O_RDONLY, MODE_READ_ONLY);
assertTranslate("rw", O_RDWR | O_CREAT,
@@ -695,8 +694,7 @@
}
@Test
- @IgnoreUnderRavenwood(reason = "Requires kernel support")
- public void testMalformedTransate_int() throws Exception {
+ public void testMalformedTransate_int() {
try {
// The non-standard Linux access mode 3 should throw
// an IllegalArgumentException.
@@ -707,8 +705,7 @@
}
@Test
- @IgnoreUnderRavenwood(reason = "Requires kernel support")
- public void testMalformedTransate_string() throws Exception {
+ public void testMalformedTransate_string() {
try {
// The non-standard Linux access mode 3 should throw
// an IllegalArgumentException.
@@ -719,8 +716,7 @@
}
@Test
- @IgnoreUnderRavenwood(reason = "Requires kernel support")
- public void testTranslateMode_Invalid() throws Exception {
+ public void testTranslateMode_Invalid() {
try {
translateModeStringToPosix("rwx");
fail();
@@ -734,8 +730,7 @@
}
@Test
- @IgnoreUnderRavenwood(reason = "Requires kernel support")
- public void testTranslateMode_Access() throws Exception {
+ public void testTranslateMode_Access() {
assertEquals(O_RDONLY, translateModeAccessToPosix(F_OK));
assertEquals(O_RDONLY, translateModeAccessToPosix(R_OK));
assertEquals(O_WRONLY, translateModeAccessToPosix(W_OK));
@@ -744,7 +739,7 @@
}
@Test
- @IgnoreUnderRavenwood(reason = "Requires kernel support")
+ @DisabledOnRavenwood(reason = "Requires kernel support")
public void testConvertToModernFd() throws Exception {
final String nonce = String.valueOf(System.nanoTime());
diff --git a/core/tests/coretests/src/android/os/LocaleListTest.java b/core/tests/coretests/src/android/os/LocaleListTest.java
index 251e00f..0b8aff0 100644
--- a/core/tests/coretests/src/android/os/LocaleListTest.java
+++ b/core/tests/coretests/src/android/os/LocaleListTest.java
@@ -20,7 +20,6 @@
import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;
-import android.platform.test.annotations.IgnoreUnderRavenwood;
import android.platform.test.ravenwood.RavenwoodRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -33,7 +32,6 @@
import java.util.Locale;
@RunWith(AndroidJUnit4.class)
-@IgnoreUnderRavenwood(blockedBy = LocaleList.class)
public class LocaleListTest {
@Rule
public final RavenwoodRule mRavenwood = new RavenwoodRule();
diff --git a/core/tests/coretests/src/com/android/internal/app/BilingualSuggestedLocaleAdapterTest.java b/core/tests/coretests/src/com/android/internal/app/BilingualSuggestedLocaleAdapterTest.java
index e8aac11..d577e0f 100644
--- a/core/tests/coretests/src/com/android/internal/app/BilingualSuggestedLocaleAdapterTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/BilingualSuggestedLocaleAdapterTest.java
@@ -18,7 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.internal.app.LocaleHelper.LocaleInfoComparator;
import com.android.internal.app.LocaleStore.LocaleInfo;
diff --git a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
index dbabcea..73a64fc 100644
--- a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
@@ -57,8 +57,8 @@
import android.provider.Settings;
import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.rule.ActivityTestRule;
-import androidx.test.runner.AndroidJUnit4;
import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
diff --git a/core/tests/coretests/src/com/android/internal/app/NoOpResolverComparatorTest.java b/core/tests/coretests/src/com/android/internal/app/NoOpResolverComparatorTest.java
index 22c319c..0ed0a81 100644
--- a/core/tests/coretests/src/com/android/internal/app/NoOpResolverComparatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/NoOpResolverComparatorTest.java
@@ -22,7 +22,7 @@
import android.os.UserHandle;
import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
index ff28055..d21ab44 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
@@ -57,8 +57,8 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.espresso.Espresso;
import androidx.test.espresso.NoMatchingViewException;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.rule.ActivityTestRule;
-import androidx.test.runner.AndroidJUnit4;
import com.android.internal.R;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverAppPredictorCallbackTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverAppPredictorCallbackTest.java
index 4aca854..bde9bdb 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverAppPredictorCallbackTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverAppPredictorCallbackTest.java
@@ -21,7 +21,7 @@
import android.app.prediction.AppTargetId;
import android.os.UserHandle;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java
index 8f6cee3..90f5c24 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java
@@ -45,7 +45,7 @@
import android.util.ArrayMap;
import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
diff --git a/core/tests/coretests/src/com/android/internal/os/DebugStoreTest.java b/core/tests/coretests/src/com/android/internal/os/DebugStoreTest.java
new file mode 100644
index 0000000..786c2fc
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/DebugStoreTest.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ServiceInfo;
+import android.platform.test.annotations.DisabledOnRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.List;
+
+/**
+ * Test class for {@link DebugStore}.
+ *
+ * To run it:
+ * atest FrameworksCoreTests:com.android.internal.os.DebugStoreTest
+ */
+@RunWith(AndroidJUnit4.class)
+@DisabledOnRavenwood(blockedBy = DebugStore.class)
+@SmallTest
+public class DebugStoreTest {
+ @Rule
+ public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
+ @Mock
+ private DebugStore.DebugStoreNative mDebugStoreNativeMock;
+
+ @Captor
+ private ArgumentCaptor<List<String>> mListCaptor;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ DebugStore.setDebugStoreNative(mDebugStoreNativeMock);
+ }
+
+ @Test
+ public void testRecordServiceOnStart() {
+ Intent intent = new Intent();
+ intent.setAction("com.android.ACTION");
+ intent.setComponent(new ComponentName("com.android", "androidService"));
+ intent.setPackage("com.android");
+
+ when(mDebugStoreNativeMock.beginEvent(anyString(), anyList())).thenReturn(1L);
+
+ long eventId = DebugStore.recordServiceOnStart(1, 0, intent);
+
+ verify(mDebugStoreNativeMock).beginEvent(eq("SvcStart"), mListCaptor.capture());
+ List<String> capturedList = mListCaptor.getValue();
+ assertThat(capturedList).containsExactly(
+ "stId", "1",
+ "flg", "0",
+ "act", "com.android.ACTION",
+ "comp", "ComponentInfo{com.android/androidService}",
+ "pkg", "com.android"
+ ).inOrder();
+ assertThat(eventId).isEqualTo(1L);
+ }
+
+ @Test
+ public void testRecordServiceCreate() {
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.name = "androidService";
+ serviceInfo.packageName = "com.android";
+
+ when(mDebugStoreNativeMock.beginEvent(anyString(), anyList())).thenReturn(2L);
+
+ long eventId = DebugStore.recordServiceCreate(serviceInfo);
+
+ verify(mDebugStoreNativeMock).beginEvent(eq("SvcCreate"), mListCaptor.capture());
+ List<String> capturedList = mListCaptor.getValue();
+ assertThat(capturedList).containsExactly(
+ "name", "androidService",
+ "pkg", "com.android"
+ ).inOrder();
+ assertThat(eventId).isEqualTo(2L);
+ }
+
+ @Test
+ public void testRecordServiceBind() {
+ Intent intent = new Intent();
+ intent.setAction("com.android.ACTION");
+ intent.setComponent(new ComponentName("com.android", "androidService"));
+ intent.setPackage("com.android");
+
+ when(mDebugStoreNativeMock.beginEvent(anyString(), anyList())).thenReturn(3L);
+
+ long eventId = DebugStore.recordServiceBind(true, intent);
+
+ verify(mDebugStoreNativeMock).beginEvent(eq("SvcBind"), mListCaptor.capture());
+ List<String> capturedList = mListCaptor.getValue();
+ assertThat(capturedList).containsExactly(
+ "rebind", "true",
+ "act", "com.android.ACTION",
+ "cmp", "ComponentInfo{com.android/androidService}",
+ "pkg", "com.android"
+ ).inOrder();
+ assertThat(eventId).isEqualTo(3L);
+ }
+
+ @Test
+ public void testRecordGoAsync() {
+ DebugStore.recordGoAsync("androidReceiver");
+
+ verify(mDebugStoreNativeMock).recordEvent(eq("GoAsync"), mListCaptor.capture());
+ List<String> capturedList = mListCaptor.getValue();
+ assertThat(capturedList).containsExactly(
+ "tname", Thread.currentThread().getName(),
+ "tid", String.valueOf(Thread.currentThread().getId()),
+ "rcv", "androidReceiver"
+ ).inOrder();
+ }
+
+ @Test
+ public void testRecordFinish() {
+ DebugStore.recordFinish("androidReceiver");
+
+ verify(mDebugStoreNativeMock).recordEvent(eq("Finish"), mListCaptor.capture());
+ List<String> capturedList = mListCaptor.getValue();
+ assertThat(capturedList).containsExactly(
+ "tname", Thread.currentThread().getName(),
+ "tid", String.valueOf(Thread.currentThread().getId()),
+ "rcv", "androidReceiver"
+ ).inOrder();
+ }
+
+ @Test
+ public void testRecordLongLooperMessage() {
+ DebugStore.recordLongLooperMessage(100, "androidHandler", 500L);
+
+ verify(mDebugStoreNativeMock).recordEvent(eq("LooperMsg"), mListCaptor.capture());
+ List<String> capturedList = mListCaptor.getValue();
+ assertThat(capturedList).containsExactly(
+ "code", "100",
+ "trgt", "androidHandler",
+ "elapsed", "500"
+ ).inOrder();
+ }
+
+ @Test
+ public void testRecordBroadcastHandleReceiver() {
+ Intent intent = new Intent();
+ intent.setAction("com.android.ACTION");
+ intent.setComponent(new ComponentName("com.android", "androidReceiver"));
+ intent.setPackage("com.android");
+
+ when(mDebugStoreNativeMock.beginEvent(anyString(), anyList())).thenReturn(4L);
+
+ long eventId = DebugStore.recordBroadcastHandleReceiver(intent);
+
+ verify(mDebugStoreNativeMock).beginEvent(eq("HandleReceiver"), mListCaptor.capture());
+ List<String> capturedList = mListCaptor.getValue();
+ assertThat(capturedList).containsExactly(
+ "tname", Thread.currentThread().getName(),
+ "tid", String.valueOf(Thread.currentThread().getId()),
+ "act", "com.android.ACTION",
+ "cmp", "ComponentInfo{com.android/androidReceiver}",
+ "pkg", "com.android"
+ ).inOrder();
+ assertThat(eventId).isEqualTo(4L);
+ }
+
+ @Test
+ public void testRecordEventEnd() {
+ DebugStore.recordEventEnd(1L);
+
+ verify(mDebugStoreNativeMock).endEvent(eq(1L), anyList());
+ }
+
+ @Test
+ public void testRecordServiceOnStartWithNullIntent() {
+ when(mDebugStoreNativeMock.beginEvent(anyString(), anyList())).thenReturn(5L);
+
+ long eventId = DebugStore.recordServiceOnStart(1, 0, null);
+
+ verify(mDebugStoreNativeMock).beginEvent(eq("SvcStart"), mListCaptor.capture());
+ List<String> capturedList = mListCaptor.getValue();
+ assertThat(capturedList).containsExactly(
+ "stId", "1",
+ "flg", "0",
+ "act", "null",
+ "comp", "null",
+ "pkg", "null"
+ ).inOrder();
+ assertThat(eventId).isEqualTo(5L);
+ }
+
+ @Test
+ public void testRecordServiceCreateWithNullServiceInfo() {
+ when(mDebugStoreNativeMock.beginEvent(anyString(), anyList())).thenReturn(6L);
+
+ long eventId = DebugStore.recordServiceCreate(null);
+
+ verify(mDebugStoreNativeMock).beginEvent(eq("SvcCreate"), mListCaptor.capture());
+ List<String> capturedList = mListCaptor.getValue();
+ assertThat(capturedList).containsExactly(
+ "name", "null",
+ "pkg", "null"
+ ).inOrder();
+ assertThat(eventId).isEqualTo(6L);
+ }
+
+ @Test
+ public void testRecordServiceBindWithNullIntent() {
+ when(mDebugStoreNativeMock.beginEvent(anyString(), anyList())).thenReturn(7L);
+
+ long eventId = DebugStore.recordServiceBind(false, null);
+
+ verify(mDebugStoreNativeMock).beginEvent(eq("SvcBind"), mListCaptor.capture());
+ List<String> capturedList = mListCaptor.getValue();
+ assertThat(capturedList).containsExactly(
+ "rebind", "false",
+ "act", "null",
+ "cmp", "null",
+ "pkg", "null"
+ ).inOrder();
+ assertThat(eventId).isEqualTo(7L);
+ }
+
+ @Test
+ public void testRecordBroadcastHandleReceiverWithNullIntent() {
+ when(mDebugStoreNativeMock.beginEvent(anyString(), anyList())).thenReturn(8L);
+
+ long eventId = DebugStore.recordBroadcastHandleReceiver(null);
+
+ verify(mDebugStoreNativeMock).beginEvent(eq("HandleReceiver"), mListCaptor.capture());
+ List<String> capturedList = mListCaptor.getValue();
+ assertThat(capturedList).containsExactly(
+ "tname", Thread.currentThread().getName(),
+ "tid", String.valueOf(Thread.currentThread().getId()),
+ "act", "null",
+ "cmp", "null",
+ "pkg", "null"
+ ).inOrder();
+ assertThat(eventId).isEqualTo(8L);
+ }
+
+ @Test
+ public void testRecordGoAsyncWithNullReceiverClassName() {
+ DebugStore.recordGoAsync(null);
+
+ verify(mDebugStoreNativeMock).recordEvent(eq("GoAsync"), mListCaptor.capture());
+ List<String> capturedList = mListCaptor.getValue();
+ assertThat(capturedList).containsExactly(
+ "tname", Thread.currentThread().getName(),
+ "tid", String.valueOf(Thread.currentThread().getId()),
+ "rcv", "null"
+ ).inOrder();
+ }
+
+ @Test
+ public void testRecordFinishWithNullReceiverClassName() {
+ DebugStore.recordFinish(null);
+
+ verify(mDebugStoreNativeMock).recordEvent(eq("Finish"), mListCaptor.capture());
+ List<String> capturedList = mListCaptor.getValue();
+ assertThat(capturedList).containsExactly(
+ "tname", Thread.currentThread().getName(),
+ "tid", String.valueOf(Thread.currentThread().getId()),
+ "rcv", "null"
+ ).inOrder();
+ }
+
+ @Test
+ public void testRecordLongLooperMessageWithNullTargetClass() {
+ DebugStore.recordLongLooperMessage(200, null, 1000L);
+
+ verify(mDebugStoreNativeMock).recordEvent(eq("LooperMsg"), mListCaptor.capture());
+ List<String> capturedList = mListCaptor.getValue();
+ assertThat(capturedList).containsExactly(
+ "code", "200",
+ "trgt", "null",
+ "elapsed", "1000"
+ ).inOrder();
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java b/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
index af2a2bb..c733bae 100644
--- a/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
+++ b/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
@@ -21,7 +21,6 @@
import static com.google.common.truth.Truth.assertThat;
import android.graphics.Rect;
-import android.os.Binder;
import android.os.Parcel;
import android.os.UserHandle;
import android.util.ArrayMap;
@@ -63,7 +62,6 @@
0x10 /* imeBackDisposition */,
false /* showImeSwitcher */,
0x20 /* disabledFlags2 */,
- new Binder() /* imeToken */,
true /* navbarColorManagedByIme */,
BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE,
WindowInsets.Type.defaultVisible(),
@@ -85,7 +83,6 @@
assertThat(copy.mImeBackDisposition).isEqualTo(original.mImeBackDisposition);
assertThat(copy.mShowImeSwitcher).isEqualTo(original.mShowImeSwitcher);
assertThat(copy.mDisabledFlags2).isEqualTo(original.mDisabledFlags2);
- assertThat(copy.mImeToken).isSameInstanceAs(original.mImeToken);
assertThat(copy.mNavbarColorManagedByIme).isEqualTo(original.mNavbarColorManagedByIme);
assertThat(copy.mBehavior).isEqualTo(original.mBehavior);
assertThat(copy.mRequestedVisibleTypes).isEqualTo(original.mRequestedVisibleTypes);
diff --git a/core/tests/resourceflaggingtests/Android.bp b/core/tests/resourceflaggingtests/Android.bp
index e8bb710..dd86094 100644
--- a/core/tests/resourceflaggingtests/Android.bp
+++ b/core/tests/resourceflaggingtests/Android.bp
@@ -34,12 +34,24 @@
}
genrule {
+ name: "resource-flagging-test-app-resources-compile2",
+ tools: ["aapt2"],
+ srcs: [
+ "flagged_resources_res/values/bools2.xml",
+ ],
+ out: ["values_bools2.arsc.flat"],
+ cmd: "$(location aapt2) compile $(in) -o $(genDir) " +
+ "--feature-flags test.package.falseFlag:ro=false,test.package.trueFlag:ro=true",
+}
+
+genrule {
name: "resource-flagging-test-app-apk",
tools: ["aapt2"],
// The first input file in the list must be the manifest
srcs: [
"TestAppAndroidManifest.xml",
":resource-flagging-test-app-resources-compile",
+ ":resource-flagging-test-app-resources-compile2",
],
out: ["resapp.apk"],
cmd: "$(location aapt2) link -o $(out) --manifest $(in)",
diff --git a/core/tests/resourceflaggingtests/flagged_resources_res/values/bools.xml b/core/tests/resourceflaggingtests/flagged_resources_res/values/bools.xml
index f4defd9..8d01465 100644
--- a/core/tests/resourceflaggingtests/flagged_resources_res/values/bools.xml
+++ b/core/tests/resourceflaggingtests/flagged_resources_res/values/bools.xml
@@ -5,4 +5,6 @@
<bool name="res2">false</bool>
<bool name="res2" android:featureFlag="test.package.trueFlag">true</bool>
+
+ <bool name="res3">false</bool>
</resources>
\ No newline at end of file
diff --git a/core/tests/resourceflaggingtests/flagged_resources_res/values/bools2.xml b/core/tests/resourceflaggingtests/flagged_resources_res/values/bools2.xml
new file mode 100644
index 0000000..e7563aa
--- /dev/null
+++ b/core/tests/resourceflaggingtests/flagged_resources_res/values/bools2.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <bool name="res3" android:featureFlag="test.package.trueFlag">true</bool>
+</resources>
\ No newline at end of file
diff --git a/core/tests/resourceflaggingtests/src/com/android/resourceflaggingtests/ResourceFlaggingTest.java b/core/tests/resourceflaggingtests/src/com/android/resourceflaggingtests/ResourceFlaggingTest.java
index a0cbe3c..ad8542e 100644
--- a/core/tests/resourceflaggingtests/src/com/android/resourceflaggingtests/ResourceFlaggingTest.java
+++ b/core/tests/resourceflaggingtests/src/com/android/resourceflaggingtests/ResourceFlaggingTest.java
@@ -63,6 +63,11 @@
assertThat(getBoolean("res2")).isTrue();
}
+ @Test
+ public void testFlagEnabledDifferentCompilationUnit() {
+ assertThat(getBoolean("res3")).isTrue();
+ }
+
private boolean getBoolean(String name) {
int resId = mResources.getIdentifier(name, "bool", "com.android.intenal.flaggedresources");
assertThat(resId).isNotEqualTo(0);
diff --git a/core/tests/vibrator/src/android/os/VibrationEffectTest.java b/core/tests/vibrator/src/android/os/VibrationEffectTest.java
index 098ade4..bd3d944 100644
--- a/core/tests/vibrator/src/android/os/VibrationEffectTest.java
+++ b/core/tests/vibrator/src/android/os/VibrationEffectTest.java
@@ -1071,6 +1071,27 @@
.isHapticFeedbackCandidate());
}
+ @Test
+ public void testParcelingComposed() {
+ Parcel p = Parcel.obtain();
+ VibrationEffect effect = VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK);
+ effect.writeToParcel(p, 0);
+ p.setDataPosition(0);
+ VibrationEffect parceledEffect = VibrationEffect.Composed.CREATOR.createFromParcel(p);
+ assertThat(parceledEffect).isEqualTo(effect);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.os.vibrator.Flags.FLAG_VENDOR_VIBRATION_EFFECTS)
+ public void testParcelingVendorEffect() {
+ Parcel p = Parcel.obtain();
+ VibrationEffect effect = VibrationEffect.createVendorEffect(createNonEmptyBundle());
+ effect.writeToParcel(p, 0);
+ p.setDataPosition(0);
+ VibrationEffect parceledEffect = VibrationEffect.VendorEffect.CREATOR.createFromParcel(p);
+ assertThat(parceledEffect).isEqualTo(effect);
+ }
+
private void assertArrayEq(long[] expected, long[] actual) {
assertTrue(
String.format("Expected pattern %s, but was %s",
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java
index b2bc3de..37f0067 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java
@@ -18,8 +18,8 @@
import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;
-import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_UNKNOWN;
-import static androidx.window.common.CommonFoldingFeature.parseListFromString;
+import static androidx.window.common.layout.CommonFoldingFeature.COMMON_STATE_UNKNOWN;
+import static androidx.window.common.layout.CommonFoldingFeature.parseListFromString;
import android.annotation.NonNull;
import android.content.Context;
@@ -31,6 +31,9 @@
import android.util.Log;
import android.util.SparseIntArray;
+import androidx.window.common.layout.CommonFoldingFeature;
+import androidx.window.common.layout.DisplayFoldFeatureCommon;
+
import com.android.internal.R;
import java.util.ArrayList;
@@ -200,6 +203,23 @@
/**
+ * Returns the list of supported {@link DisplayFoldFeatureCommon} calculated from the
+ * {@link DeviceStateManagerFoldingFeatureProducer}.
+ */
+ @NonNull
+ public List<DisplayFoldFeatureCommon> getDisplayFeatures() {
+ final List<DisplayFoldFeatureCommon> foldFeatures = new ArrayList<>();
+ final List<CommonFoldingFeature> folds = getFoldsWithUnknownState();
+
+ final boolean isHalfOpenedSupported = isHalfOpenedSupported();
+ for (CommonFoldingFeature fold : folds) {
+ foldFeatures.add(DisplayFoldFeatureCommon.create(fold, isHalfOpenedSupported));
+ }
+ return foldFeatures;
+ }
+
+
+ /**
* Returns {@code true} if the device supports half-opened mode, {@code false} otherwise.
*/
public boolean isHalfOpenedSupported() {
@@ -211,7 +231,7 @@
* @param storeFeaturesConsumer a consumer to collect the data when it is first available.
*/
@Override
- public void getData(Consumer<List<CommonFoldingFeature>> storeFeaturesConsumer) {
+ public void getData(@NonNull Consumer<List<CommonFoldingFeature>> storeFeaturesConsumer) {
mRawFoldSupplier.getData((String displayFeaturesString) -> {
if (TextUtils.isEmpty(displayFeaturesString)) {
storeFeaturesConsumer.accept(new ArrayList<>());
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/RawFoldingFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/RawFoldingFeatureProducer.java
index 6d758f1..9651918 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/common/RawFoldingFeatureProducer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/common/RawFoldingFeatureProducer.java
@@ -26,6 +26,8 @@
import android.provider.Settings;
import android.text.TextUtils;
+import androidx.window.common.layout.CommonFoldingFeature;
+
import com.android.internal.R;
import java.util.Optional;
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/collections/ListUtil.java b/libs/WindowManager/Jetpack/src/androidx/window/common/collections/ListUtil.java
new file mode 100644
index 0000000..e72459f
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/common/collections/ListUtil.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.common.collections;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+
+/**
+ * A class to contain utility methods for {@link List}.
+ */
+public final class ListUtil {
+
+ private ListUtil() {}
+
+ /**
+ * Returns a new {@link List} that is created by applying the {@code transformer} to the
+ * {@code source} list.
+ */
+ public static <T, U> List<U> map(List<T> source, Function<T, U> transformer) {
+ final List<U> target = new ArrayList<>();
+ for (int i = 0; i < source.size(); i++) {
+ target.add(transformer.apply(source.get(i)));
+ }
+ return target;
+ }
+}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java b/libs/WindowManager/Jetpack/src/androidx/window/common/layout/CommonFoldingFeature.java
similarity index 99%
rename from libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java
rename to libs/WindowManager/Jetpack/src/androidx/window/common/layout/CommonFoldingFeature.java
index b95bca1..85c4fe1 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/common/layout/CommonFoldingFeature.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.window.common;
+package androidx.window.common.layout;
import static androidx.window.common.ExtensionHelper.isZero;
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/layout/DisplayFoldFeatureCommon.java b/libs/WindowManager/Jetpack/src/androidx/window/common/layout/DisplayFoldFeatureCommon.java
new file mode 100644
index 0000000..594bd9c
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/common/layout/DisplayFoldFeatureCommon.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.common.layout;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.util.ArraySet;
+
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * A class that represents if a fold is part of the device.
+ */
+public final class DisplayFoldFeatureCommon {
+
+ /**
+ * Returns a new instance of {@link DisplayFoldFeatureCommon} based off of
+ * {@link CommonFoldingFeature} and whether or not half opened is supported.
+ */
+ public static DisplayFoldFeatureCommon create(CommonFoldingFeature foldingFeature,
+ boolean isHalfOpenedSupported) {
+ @FoldType
+ final int foldType;
+ if (foldingFeature.getType() == CommonFoldingFeature.COMMON_TYPE_HINGE) {
+ foldType = DISPLAY_FOLD_FEATURE_TYPE_HINGE;
+ } else {
+ foldType = DISPLAY_FOLD_FEATURE_TYPE_SCREEN_FOLD_IN;
+ }
+
+ final Set<Integer> properties = new ArraySet<>();
+
+ if (isHalfOpenedSupported) {
+ properties.add(DISPLAY_FOLD_FEATURE_PROPERTY_SUPPORTS_HALF_OPENED);
+ }
+ return new DisplayFoldFeatureCommon(foldType, properties);
+ }
+
+ /**
+ * The type of fold is unknown. This is here for compatibility reasons if a new type is added,
+ * and cannot be reported to an incompatible application.
+ */
+ public static final int DISPLAY_FOLD_FEATURE_TYPE_UNKNOWN = 0;
+
+ /**
+ * The type of fold is a physical hinge separating two display panels.
+ */
+ public static final int DISPLAY_FOLD_FEATURE_TYPE_HINGE = 1;
+
+ /**
+ * The type of fold is a screen that folds from 0-180.
+ */
+ public static final int DISPLAY_FOLD_FEATURE_TYPE_SCREEN_FOLD_IN = 2;
+
+ /**
+ * @hide
+ */
+ @IntDef(value = {DISPLAY_FOLD_FEATURE_TYPE_UNKNOWN, DISPLAY_FOLD_FEATURE_TYPE_HINGE,
+ DISPLAY_FOLD_FEATURE_TYPE_SCREEN_FOLD_IN})
+ public @interface FoldType {
+ }
+
+ /**
+ * The fold supports the half opened state.
+ */
+ public static final int DISPLAY_FOLD_FEATURE_PROPERTY_SUPPORTS_HALF_OPENED = 1;
+
+ @IntDef(value = {DISPLAY_FOLD_FEATURE_PROPERTY_SUPPORTS_HALF_OPENED})
+ public @interface FoldProperty {
+ }
+
+ @FoldType
+ private final int mType;
+
+ private final Set<Integer> mProperties;
+
+ /**
+ * Creates an instance of [FoldDisplayFeature].
+ *
+ * @param type the type of fold, either [FoldDisplayFeature.TYPE_HINGE] or
+ * [FoldDisplayFeature.TYPE_FOLDABLE_SCREEN]
+ * @hide
+ */
+ public DisplayFoldFeatureCommon(@FoldType int type, @NonNull Set<Integer> properties) {
+ mType = type;
+ mProperties = new ArraySet<>();
+ assertPropertiesAreValid(properties);
+ mProperties.addAll(properties);
+ }
+
+ /**
+ * Returns the type of fold that is either a hinge or a fold.
+ */
+ @FoldType
+ public int getType() {
+ return mType;
+ }
+
+ /**
+ * Returns {@code true} if the fold has the given property, {@code false} otherwise.
+ */
+ public boolean hasProperty(@FoldProperty int property) {
+ return mProperties.contains(property);
+ }
+ /**
+ * Returns {@code true} if the fold has all the given properties, {@code false} otherwise.
+ */
+ public boolean hasProperties(@NonNull @FoldProperty int... properties) {
+ for (int i = 0; i < properties.length; i++) {
+ if (!mProperties.contains(properties[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns a copy of the set of properties.
+ * @hide
+ */
+ public Set<Integer> getProperties() {
+ return new ArraySet<>(mProperties);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ DisplayFoldFeatureCommon that = (DisplayFoldFeatureCommon) o;
+ return mType == that.mType && Objects.equals(mProperties, that.mProperties);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mType, mProperties);
+ }
+
+ @Override
+ public String toString() {
+ return "DisplayFoldFeatureCommon{mType=" + mType + ", mProperties=" + mProperties + '}';
+ }
+
+ private static void assertPropertiesAreValid(@NonNull Set<Integer> properties) {
+ for (int property : properties) {
+ if (!isProperty(property)) {
+ throw new IllegalArgumentException("Property is not a valid type: " + property);
+ }
+ }
+ }
+
+ private static boolean isProperty(int property) {
+ if (property == DISPLAY_FOLD_FEATURE_PROPERTY_SUPPORTS_HALF_OPENED) {
+ return true;
+ }
+ return false;
+ }
+}
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 409cde3..7be14724 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -89,9 +89,9 @@
import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.window.common.CommonFoldingFeature;
import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
import androidx.window.common.EmptyLifecycleCallbacksAdapter;
+import androidx.window.common.layout.CommonFoldingFeature;
import androidx.window.extensions.WindowExtensions;
import androidx.window.extensions.core.util.function.Consumer;
import androidx.window.extensions.core.util.function.Function;
@@ -1334,13 +1334,24 @@
if (shouldContainerBeExpanded(container)) {
// Make sure that the existing container is expanded.
mPresenter.expandTaskFragment(wct, container);
- } else {
- // Put activity into a new expanded container.
- final TaskFragmentContainer newContainer =
- new TaskFragmentContainer.Builder(this, getTaskId(activity), activity)
- .setPendingAppearedActivity(activity).build();
- mPresenter.expandActivity(wct, newContainer.getTaskFragmentToken(), activity);
+ return;
}
+
+ final SplitContainer splitContainer = getActiveSplitForContainer(container);
+ if (splitContainer instanceof SplitPinContainer
+ && !container.isPinned() && container.getRunningActivityCount() == 1) {
+ // This is already the expected state when the pinned container is shown with an
+ // expanded activity in a standalone container on the side. Moving the activity into
+ // another new expanded container again is not necessary and could result in
+ // recursively creating new TaskFragmentContainers if the activity somehow relaunched.
+ return;
+ }
+
+ // Put activity into a new expanded container.
+ final TaskFragmentContainer newContainer =
+ new TaskFragmentContainer.Builder(this, getTaskId(activity), activity)
+ .setPendingAppearedActivity(activity).build();
+ mPresenter.expandActivity(wct, newContainer.getTaskFragmentToken(), activity);
}
/**
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/DisplayFoldFeatureUtil.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/DisplayFoldFeatureUtil.java
index a0f481a..870c92e 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/DisplayFoldFeatureUtil.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/DisplayFoldFeatureUtil.java
@@ -16,48 +16,24 @@
package androidx.window.extensions.layout;
-import androidx.window.common.CommonFoldingFeature;
-import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
-
-import java.util.ArrayList;
-import java.util.List;
+import androidx.window.common.layout.DisplayFoldFeatureCommon;
/**
* Util functions for working with {@link androidx.window.extensions.layout.DisplayFoldFeature}.
*/
-public class DisplayFoldFeatureUtil {
+public final class DisplayFoldFeatureUtil {
private DisplayFoldFeatureUtil() {}
- private static DisplayFoldFeature create(CommonFoldingFeature foldingFeature,
- boolean isHalfOpenedSupported) {
- final int foldType;
- if (foldingFeature.getType() == CommonFoldingFeature.COMMON_TYPE_HINGE) {
- foldType = DisplayFoldFeature.TYPE_HINGE;
- } else {
- foldType = DisplayFoldFeature.TYPE_SCREEN_FOLD_IN;
- }
- DisplayFoldFeature.Builder featureBuilder = new DisplayFoldFeature.Builder(foldType);
-
- if (isHalfOpenedSupported) {
- featureBuilder.addProperty(DisplayFoldFeature.FOLD_PROPERTY_SUPPORTS_HALF_OPENED);
- }
- return featureBuilder.build();
- }
-
/**
- * Returns the list of supported {@link DisplayFeature} calculated from the
- * {@link DeviceStateManagerFoldingFeatureProducer}.
+ * Returns a {@link DisplayFoldFeature} that matches the given {@link DisplayFoldFeatureCommon}.
*/
- public static List<DisplayFoldFeature> extractDisplayFoldFeatures(
- DeviceStateManagerFoldingFeatureProducer producer) {
- List<DisplayFoldFeature> foldFeatures = new ArrayList<>();
- List<CommonFoldingFeature> folds = producer.getFoldsWithUnknownState();
-
- final boolean isHalfOpenedSupported = producer.isHalfOpenedSupported();
- for (CommonFoldingFeature fold : folds) {
- foldFeatures.add(DisplayFoldFeatureUtil.create(fold, isHalfOpenedSupported));
+ public static DisplayFoldFeature translate(DisplayFoldFeatureCommon foldFeatureCommon) {
+ final DisplayFoldFeature.Builder builder =
+ new DisplayFoldFeature.Builder(foldFeatureCommon.getType());
+ for (int property: foldFeatureCommon.getProperties()) {
+ builder.addProperty(property);
}
- return foldFeatures;
+ return builder.build();
}
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
index a3ef68a..f1ea19a 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
@@ -19,11 +19,11 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
-import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_FLAT;
-import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_HALF_OPENED;
import static androidx.window.common.ExtensionHelper.isZero;
import static androidx.window.common.ExtensionHelper.rotateRectToDisplayRotation;
import static androidx.window.common.ExtensionHelper.transformToWindowSpaceRect;
+import static androidx.window.common.layout.CommonFoldingFeature.COMMON_STATE_FLAT;
+import static androidx.window.common.layout.CommonFoldingFeature.COMMON_STATE_HALF_OPENED;
import android.app.Activity;
import android.app.ActivityThread;
@@ -45,9 +45,10 @@
import androidx.annotation.Nullable;
import androidx.annotation.UiContext;
import androidx.annotation.VisibleForTesting;
-import androidx.window.common.CommonFoldingFeature;
import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
import androidx.window.common.EmptyLifecycleCallbacksAdapter;
+import androidx.window.common.collections.ListUtil;
+import androidx.window.common.layout.CommonFoldingFeature;
import androidx.window.extensions.core.util.function.Consumer;
import androidx.window.extensions.util.DeduplicateConsumer;
@@ -95,8 +96,8 @@
.registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged());
mFoldingFeatureProducer = foldingFeatureProducer;
mFoldingFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged);
- final List<DisplayFoldFeature> displayFoldFeatures =
- DisplayFoldFeatureUtil.extractDisplayFoldFeatures(mFoldingFeatureProducer);
+ final List<DisplayFoldFeature> displayFoldFeatures = ListUtil.map(
+ mFoldingFeatureProducer.getDisplayFeatures(), DisplayFoldFeatureUtil::translate);
mSupportedWindowFeatures = new SupportedWindowFeatures.Builder(displayFoldFeatures).build();
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java
index b63fd08..60bc7be 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java
@@ -26,10 +26,10 @@
import androidx.annotation.NonNull;
import androidx.window.common.BaseDataProducer;
-import androidx.window.common.CommonFoldingFeature;
import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
import androidx.window.common.EmptyLifecycleCallbacksAdapter;
import androidx.window.common.RawFoldingFeatureProducer;
+import androidx.window.common.layout.CommonFoldingFeature;
import java.util.ArrayList;
import java.util.List;
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SidecarHelper.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SidecarHelper.java
index 4fd03e4..6e0e711 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SidecarHelper.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SidecarHelper.java
@@ -26,7 +26,7 @@
import android.graphics.Rect;
import android.os.IBinder;
-import androidx.window.common.CommonFoldingFeature;
+import androidx.window.common.layout.CommonFoldingFeature;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/common/collections/ListUtilTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/common/collections/ListUtilTest.java
new file mode 100644
index 0000000..a077bdf
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/common/collections/ListUtilTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.common.collections;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test class for {@link ListUtil}.
+ *
+ * Build/Install/Run:
+ * atest WMJetpackUnitTests:ListUtil
+ */
+public class ListUtilTest {
+
+ @Test
+ public void test_map_empty_returns_empty() {
+ final List<String> emptyList = new ArrayList<>();
+ final List<Integer> result = ListUtil.map(emptyList, String::length);
+ assertThat(result).isEmpty();
+ }
+
+ @Test
+ public void test_map_maintains_order() {
+ final List<String> source = new ArrayList<>();
+ source.add("a");
+ source.add("aa");
+
+ final List<Integer> result = ListUtil.map(source, String::length);
+
+ assertThat(result).containsExactly(1, 2).inOrder();
+ }
+}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/common/layout/DisplayFoldFeatureCommonTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/common/layout/DisplayFoldFeatureCommonTest.java
new file mode 100644
index 0000000..6c17851
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/common/layout/DisplayFoldFeatureCommonTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.common.layout;
+
+import static androidx.window.common.layout.CommonFoldingFeature.COMMON_STATE_UNKNOWN;
+import static androidx.window.common.layout.CommonFoldingFeature.COMMON_TYPE_FOLD;
+import static androidx.window.common.layout.CommonFoldingFeature.COMMON_TYPE_HINGE;
+import static androidx.window.common.layout.DisplayFoldFeatureCommon.DISPLAY_FOLD_FEATURE_PROPERTY_SUPPORTS_HALF_OPENED;
+import static androidx.window.common.layout.DisplayFoldFeatureCommon.DISPLAY_FOLD_FEATURE_TYPE_HINGE;
+import static androidx.window.common.layout.DisplayFoldFeatureCommon.DISPLAY_FOLD_FEATURE_TYPE_SCREEN_FOLD_IN;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.graphics.Rect;
+import android.util.ArraySet;
+
+import org.junit.Test;
+
+import java.util.Set;
+
+/**
+ * Test class for {@link DisplayFoldFeatureCommon}.
+ *
+ * Build/Install/Run:
+ * atest WMJetpackUnitTests:DisplayFoldFeatureCommonTest
+ */
+public class DisplayFoldFeatureCommonTest {
+
+ @Test
+ public void test_different_type_not_equals() {
+ final Set<Integer> properties = new ArraySet<>();
+ final DisplayFoldFeatureCommon first =
+ new DisplayFoldFeatureCommon(DISPLAY_FOLD_FEATURE_TYPE_HINGE, properties);
+ final DisplayFoldFeatureCommon second =
+ new DisplayFoldFeatureCommon(DISPLAY_FOLD_FEATURE_TYPE_SCREEN_FOLD_IN, properties);
+
+ assertThat(first).isEqualTo(second);
+ }
+
+ @Test
+ public void test_different_property_set_not_equals() {
+ final Set<Integer> firstProperties = new ArraySet<>();
+ final Set<Integer> secondProperties = new ArraySet<>();
+ secondProperties.add(DISPLAY_FOLD_FEATURE_PROPERTY_SUPPORTS_HALF_OPENED);
+ final DisplayFoldFeatureCommon first =
+ new DisplayFoldFeatureCommon(DISPLAY_FOLD_FEATURE_TYPE_HINGE, firstProperties);
+ final DisplayFoldFeatureCommon second =
+ new DisplayFoldFeatureCommon(DISPLAY_FOLD_FEATURE_TYPE_HINGE, secondProperties);
+
+ assertThat(first).isNotEqualTo(second);
+ }
+
+ @Test
+ public void test_check_single_property_exists() {
+ final Set<Integer> properties = new ArraySet<>();
+ properties.add(DISPLAY_FOLD_FEATURE_PROPERTY_SUPPORTS_HALF_OPENED);
+ final DisplayFoldFeatureCommon foldFeatureCommon =
+ new DisplayFoldFeatureCommon(DISPLAY_FOLD_FEATURE_TYPE_HINGE, properties);
+
+ assertThat(
+ foldFeatureCommon.hasProperty(DISPLAY_FOLD_FEATURE_PROPERTY_SUPPORTS_HALF_OPENED))
+ .isTrue();
+ }
+
+ @Test
+ public void test_check_multiple_properties_exists() {
+ final Set<Integer> properties = new ArraySet<>();
+ properties.add(DISPLAY_FOLD_FEATURE_PROPERTY_SUPPORTS_HALF_OPENED);
+ final DisplayFoldFeatureCommon foldFeatureCommon =
+ new DisplayFoldFeatureCommon(DISPLAY_FOLD_FEATURE_TYPE_HINGE, properties);
+
+ assertThat(foldFeatureCommon.hasProperties(
+ DISPLAY_FOLD_FEATURE_PROPERTY_SUPPORTS_HALF_OPENED))
+ .isTrue();
+ }
+
+ @Test
+ public void test_properties_matches_getter() {
+ final Set<Integer> properties = new ArraySet<>();
+ properties.add(DISPLAY_FOLD_FEATURE_PROPERTY_SUPPORTS_HALF_OPENED);
+ final DisplayFoldFeatureCommon foldFeatureCommon =
+ new DisplayFoldFeatureCommon(DISPLAY_FOLD_FEATURE_TYPE_HINGE, properties);
+
+ assertThat(foldFeatureCommon.getProperties()).isEqualTo(properties);
+ }
+
+ @Test
+ public void test_type_matches_getter() {
+ final Set<Integer> properties = new ArraySet<>();
+ final DisplayFoldFeatureCommon foldFeatureCommon =
+ new DisplayFoldFeatureCommon(DISPLAY_FOLD_FEATURE_TYPE_HINGE, properties);
+
+ assertThat(foldFeatureCommon.getType()).isEqualTo(DISPLAY_FOLD_FEATURE_TYPE_HINGE);
+ }
+
+ @Test
+ public void test_create_half_opened_feature() {
+ final CommonFoldingFeature foldingFeature =
+ new CommonFoldingFeature(COMMON_TYPE_HINGE, COMMON_STATE_UNKNOWN, new Rect());
+ final DisplayFoldFeatureCommon foldFeatureCommon = DisplayFoldFeatureCommon.create(
+ foldingFeature, true);
+
+ assertThat(foldFeatureCommon.getType()).isEqualTo(DISPLAY_FOLD_FEATURE_TYPE_HINGE);
+ assertThat(
+ foldFeatureCommon.hasProperty(DISPLAY_FOLD_FEATURE_PROPERTY_SUPPORTS_HALF_OPENED))
+ .isTrue();
+ }
+
+ @Test
+ public void test_create_fold_feature_no_half_opened() {
+ final CommonFoldingFeature foldingFeature =
+ new CommonFoldingFeature(COMMON_TYPE_FOLD, COMMON_STATE_UNKNOWN, new Rect());
+ final DisplayFoldFeatureCommon foldFeatureCommon = DisplayFoldFeatureCommon.create(
+ foldingFeature, true);
+
+ assertThat(foldFeatureCommon.getType()).isEqualTo(DISPLAY_FOLD_FEATURE_TYPE_SCREEN_FOLD_IN);
+ assertThat(
+ foldFeatureCommon.hasProperty(DISPLAY_FOLD_FEATURE_PROPERTY_SUPPORTS_HALF_OPENED))
+ .isTrue();
+ }
+}
diff --git a/libs/WindowManager/Shell/res/drawable/desktop_mode_ic_handle_menu_new_window.xml b/libs/WindowManager/Shell/res/drawable/desktop_mode_ic_handle_menu_new_window.xml
new file mode 100644
index 0000000..c154059
--- /dev/null
+++ b/libs/WindowManager/Shell/res/drawable/desktop_mode_ic_handle_menu_new_window.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="20dp"
+ android:height="20dp"
+ android:viewportWidth="20"
+ android:viewportHeight="20">
+ <path
+ android:pathData="M15 16V14H13V12.5H15V10.5H16.5V12.5H18.5V14H16.5V16H15ZM3.5 17C3.09722 17 2.74306 16.8542 2.4375 16.5625C2.14583 16.2569 2 15.9028 2 15.5V4.5C2 4.08333 2.14583 3.72917 2.4375 3.4375C2.74306 3.14583 3.09722 3 3.5 3H14.5C14.9167 3 15.2708 3.14583 15.5625 3.4375C15.8542 3.72917 16 4.08333 16 4.5V9H14.5V7H3.5V15.5H13.625V17H3.5ZM3.5 5.5H14.5V4.5H3.5V5.5ZM3.5 5.5V4.5V5.5Z"
+ android:fillColor="#1C1C14"/>
+</vector>
diff --git a/libs/WindowManager/Shell/res/layout/bubble_bar_menu_view.xml b/libs/WindowManager/Shell/res/layout/bubble_bar_menu_view.xml
index 82e5aee..1cbd0e6 100644
--- a/libs/WindowManager/Shell/res/layout/bubble_bar_menu_view.xml
+++ b/libs/WindowManager/Shell/res/layout/bubble_bar_menu_view.xml
@@ -71,6 +71,8 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="@dimen/bubble_bar_manage_menu_section_spacing"
+ android:clipChildren="true"
+ android:clipToOutline="true"
android:background="@drawable/bubble_manage_menu_bg"
android:elevation="@dimen/bubble_manage_menu_elevation" />
diff --git a/libs/WindowManager/Shell/res/layout/compat_ui_layout.xml b/libs/WindowManager/Shell/res/layout/compat_ui_layout.xml
index 257fe15..62782a7 100644
--- a/libs/WindowManager/Shell/res/layout/compat_ui_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/compat_ui_layout.xml
@@ -21,38 +21,6 @@
android:orientation="vertical"
android:gravity="bottom|end">
- <include android:id="@+id/camera_compat_hint"
- android:visibility="gone"
- android:layout_width="@dimen/camera_compat_hint_width"
- android:layout_height="wrap_content"
- layout="@layout/compat_mode_hint"/>
-
- <LinearLayout
- android:id="@+id/camera_compat_control"
- android:visibility="gone"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:clipToPadding="false"
- android:layout_marginEnd="@dimen/compat_button_margin"
- android:layout_marginBottom="@dimen/compat_button_margin"
- android:orientation="vertical">
-
- <ImageButton
- android:id="@+id/camera_compat_treatment_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@android:color/transparent"/>
-
- <ImageButton
- android:id="@+id/camera_compat_dismiss_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/camera_compat_dismiss_ripple"
- android:background="@android:color/transparent"
- android:contentDescription="@string/camera_compat_dismiss_button_description"/>
-
- </LinearLayout>
-
<include android:id="@+id/size_compat_hint"
android:visibility="gone"
android:layout_width="@dimen/compat_hint_width"
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml
index 49d9029..eea3de8 100644
--- a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml
+++ b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml
@@ -125,7 +125,7 @@
<LinearLayout
android:id="@+id/more_actions_pill"
android:layout_width="match_parent"
- android:layout_height="@dimen/desktop_mode_handle_menu_more_actions_pill_height"
+ android:layout_height="wrap_content"
android:layout_marginTop="@dimen/desktop_mode_handle_menu_pill_spacing_margin"
android:layout_marginStart="1dp"
android:orientation="vertical"
@@ -139,6 +139,14 @@
android:drawableStart="@drawable/desktop_mode_ic_handle_menu_screenshot"
android:drawableTint="?androidprv:attr/materialColorOnSurface"
style="@style/DesktopModeHandleMenuActionButton"/>
+
+ <Button
+ android:id="@+id/new_window_button"
+ android:contentDescription="@string/new_window_text"
+ android:text="@string/new_window_text"
+ android:drawableStart="@drawable/desktop_mode_ic_handle_menu_new_window"
+ android:drawableTint="?androidprv:attr/materialColorOnSurface"
+ style="@style/DesktopModeHandleMenuActionButton" />
</LinearLayout>
<LinearLayout
diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml
index e476db0..e58ff6a 100644
--- a/libs/WindowManager/Shell/res/values-af/strings.xml
+++ b/libs/WindowManager/Shell/res/values-af/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Maak klein"</string>
<string name="close_button_text" msgid="2913281996024033299">"Maak toe"</string>
<string name="back_button_text" msgid="1469718707134137085">"Terug"</string>
- <string name="handle_text" msgid="1766582106752184456">"Handvatsel"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Apphandvatsel"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Appikoon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Volskerm"</string>
<string name="desktop_text" msgid="1077633567027630454">"Rekenaarmodus"</string>
diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml
index 33fea2b..3208ea9 100644
--- a/libs/WindowManager/Shell/res/values-am/strings.xml
+++ b/libs/WindowManager/Shell/res/values-am/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"አሳንስ"</string>
<string name="close_button_text" msgid="2913281996024033299">"ዝጋ"</string>
<string name="back_button_text" msgid="1469718707134137085">"ተመለስ"</string>
- <string name="handle_text" msgid="1766582106752184456">"መያዣ"</string>
+ <string name="handle_text" msgid="4419667835599523257">"የመተግበሪያ መያዣ"</string>
<string name="app_icon_text" msgid="2823268023931811747">"የመተግበሪያ አዶ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ሙሉ ማያ"</string>
<string name="desktop_text" msgid="1077633567027630454">"የዴስክቶፕ ሁነታ"</string>
diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml
index b014c3b..18db50e 100644
--- a/libs/WindowManager/Shell/res/values-ar/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ar/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"تصغير"</string>
<string name="close_button_text" msgid="2913281996024033299">"إغلاق"</string>
<string name="back_button_text" msgid="1469718707134137085">"رجوع"</string>
- <string name="handle_text" msgid="1766582106752184456">"مقبض"</string>
+ <string name="handle_text" msgid="4419667835599523257">"مقبض التطبيق"</string>
<string name="app_icon_text" msgid="2823268023931811747">"رمز التطبيق"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ملء الشاشة"</string>
<string name="desktop_text" msgid="1077633567027630454">"وضع سطح المكتب"</string>
diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml
index b94ab2e..1951772 100644
--- a/libs/WindowManager/Shell/res/values-as/strings.xml
+++ b/libs/WindowManager/Shell/res/values-as/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"মিনিমাইজ কৰক"</string>
<string name="close_button_text" msgid="2913281996024033299">"বন্ধ কৰক"</string>
<string name="back_button_text" msgid="1469718707134137085">"উভতি যাওক"</string>
- <string name="handle_text" msgid="1766582106752184456">"হেণ্ডেল"</string>
+ <string name="handle_text" msgid="4419667835599523257">"এপৰ হেণ্ডেল"</string>
<string name="app_icon_text" msgid="2823268023931811747">"এপৰ চিহ্ন"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"সম্পূৰ্ণ স্ক্ৰীন"</string>
<string name="desktop_text" msgid="1077633567027630454">"ডেস্কটপ ম’ড"</string>
diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml
index 9ec44a1..32e0dd6 100644
--- a/libs/WindowManager/Shell/res/values-az/strings.xml
+++ b/libs/WindowManager/Shell/res/values-az/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Kiçildin"</string>
<string name="close_button_text" msgid="2913281996024033299">"Bağlayın"</string>
<string name="back_button_text" msgid="1469718707134137085">"Geriyə"</string>
- <string name="handle_text" msgid="1766582106752184456">"Hər kəsə açıq istifadəçi adı"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Tətbiq ləqəbi"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Tətbiq ikonası"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Tam Ekran"</string>
<string name="desktop_text" msgid="1077633567027630454">"Masaüstü Rejimi"</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 af695e7..1656e02 100644
--- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Umanjite"</string>
<string name="close_button_text" msgid="2913281996024033299">"Zatvorite"</string>
<string name="back_button_text" msgid="1469718707134137085">"Nazad"</string>
- <string name="handle_text" msgid="1766582106752184456">"Identifikator"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Identifikator aplikacije"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikacije"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Preko celog ekrana"</string>
<string name="desktop_text" msgid="1077633567027630454">"Režim za računare"</string>
diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml
index dbbc07f..26f3d3c 100644
--- a/libs/WindowManager/Shell/res/values-be/strings.xml
+++ b/libs/WindowManager/Shell/res/values-be/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Згарнуць"</string>
<string name="close_button_text" msgid="2913281996024033299">"Закрыць"</string>
<string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
- <string name="handle_text" msgid="1766582106752184456">"Маркер"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Маркер праграмы"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Значок праграмы"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"На ўвесь экран"</string>
<string name="desktop_text" msgid="1077633567027630454">"Рэжым працоўнага стала"</string>
diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml
index 8dc7915..7c4f25e 100644
--- a/libs/WindowManager/Shell/res/values-bg/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bg/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Намаляване"</string>
<string name="close_button_text" msgid="2913281996024033299">"Затваряне"</string>
<string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
- <string name="handle_text" msgid="1766582106752184456">"Манипулатор"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Манипулатор за приложението"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Икона на приложението"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Цял екран"</string>
<string name="desktop_text" msgid="1077633567027630454">"Режим за настолни компютри"</string>
diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml
index 61294ad..4286162 100644
--- a/libs/WindowManager/Shell/res/values-bn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bn/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"ছোট করুন"</string>
<string name="close_button_text" msgid="2913281996024033299">"বন্ধ করুন"</string>
<string name="back_button_text" msgid="1469718707134137085">"ফিরে যান"</string>
- <string name="handle_text" msgid="1766582106752184456">"হাতল"</string>
+ <string name="handle_text" msgid="4419667835599523257">"অ্যাপের হ্যান্ডেল"</string>
<string name="app_icon_text" msgid="2823268023931811747">"অ্যাপ আইকন"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ফুলস্ক্রিন"</string>
<string name="desktop_text" msgid="1077633567027630454">"ডেস্কটপ মোড"</string>
diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml
index 676b226..11f5e48 100644
--- a/libs/WindowManager/Shell/res/values-bs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bs/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimiziranje"</string>
<string name="close_button_text" msgid="2913281996024033299">"Zatvaranje"</string>
<string name="back_button_text" msgid="1469718707134137085">"Nazad"</string>
- <string name="handle_text" msgid="1766582106752184456">"Identifikator"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Ručica aplikacije"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikacije"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Cijeli ekran"</string>
<string name="desktop_text" msgid="1077633567027630454">"Način rada radne površine"</string>
diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml
index ce9f547..e1fc7d3 100644
--- a/libs/WindowManager/Shell/res/values-ca/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ca/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimitza"</string>
<string name="close_button_text" msgid="2913281996024033299">"Tanca"</string>
<string name="back_button_text" msgid="1469718707134137085">"Enrere"</string>
- <string name="handle_text" msgid="1766582106752184456">"Ansa"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Identificador de l\'aplicació"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Icona de l\'aplicació"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string>
<string name="desktop_text" msgid="1077633567027630454">"Mode d\'escriptori"</string>
diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml
index 6b9d85f..e428210 100644
--- a/libs/WindowManager/Shell/res/values-cs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-cs/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimalizovat"</string>
<string name="close_button_text" msgid="2913281996024033299">"Zavřít"</string>
<string name="back_button_text" msgid="1469718707134137085">"Zpět"</string>
- <string name="handle_text" msgid="1766582106752184456">"Úchyt"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Popisovač aplikace"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikace"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Celá obrazovka"</string>
<string name="desktop_text" msgid="1077633567027630454">"Režim počítače"</string>
diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml
index de7d919..36c0330 100644
--- a/libs/WindowManager/Shell/res/values-da/strings.xml
+++ b/libs/WindowManager/Shell/res/values-da/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimer"</string>
<string name="close_button_text" msgid="2913281996024033299">"Luk"</string>
<string name="back_button_text" msgid="1469718707134137085">"Tilbage"</string>
- <string name="handle_text" msgid="1766582106752184456">"Håndtag"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Apphåndtag"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Appikon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Fuld skærm"</string>
<string name="desktop_text" msgid="1077633567027630454">"Computertilstand"</string>
diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml
index e4fd311..0ad112c 100644
--- a/libs/WindowManager/Shell/res/values-de/strings.xml
+++ b/libs/WindowManager/Shell/res/values-de/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimieren"</string>
<string name="close_button_text" msgid="2913281996024033299">"Schließen"</string>
<string name="back_button_text" msgid="1469718707134137085">"Zurück"</string>
- <string name="handle_text" msgid="1766582106752184456">"Ziehpunkt"</string>
+ <string name="handle_text" msgid="4419667835599523257">"App-Ziehpunkt"</string>
<string name="app_icon_text" msgid="2823268023931811747">"App-Symbol"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Vollbild"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktopmodus"</string>
diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml
index 964166e..1e2fec1 100644
--- a/libs/WindowManager/Shell/res/values-el/strings.xml
+++ b/libs/WindowManager/Shell/res/values-el/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Ελαχιστοποίηση"</string>
<string name="close_button_text" msgid="2913281996024033299">"Κλείσιμο"</string>
<string name="back_button_text" msgid="1469718707134137085">"Πίσω"</string>
- <string name="handle_text" msgid="1766582106752184456">"Λαβή"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Λαβή εφαρμογής"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Εικονίδιο εφαρμογής"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Πλήρης οθόνη"</string>
<string name="desktop_text" msgid="1077633567027630454">"Λειτουργία επιφάνειας εργασίας"</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
index c17b9f7a..71701c9 100644
--- a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimise"</string>
<string name="close_button_text" msgid="2913281996024033299">"Close"</string>
<string name="back_button_text" msgid="1469718707134137085">"Back"</string>
- <string name="handle_text" msgid="1766582106752184456">"Handle"</string>
+ <string name="handle_text" msgid="4419667835599523257">"App handle"</string>
<string name="app_icon_text" msgid="2823268023931811747">"App icon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Full screen"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktop mode"</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
index bd8a636..5ab4af3 100644
--- a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimize"</string>
<string name="close_button_text" msgid="2913281996024033299">"Close"</string>
<string name="back_button_text" msgid="1469718707134137085">"Back"</string>
- <string name="handle_text" msgid="1766582106752184456">"Handle"</string>
+ <string name="handle_text" msgid="4419667835599523257">"App handle"</string>
<string name="app_icon_text" msgid="2823268023931811747">"App Icon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Fullscreen"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktop Mode"</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
index c17b9f7a..71701c9 100644
--- a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimise"</string>
<string name="close_button_text" msgid="2913281996024033299">"Close"</string>
<string name="back_button_text" msgid="1469718707134137085">"Back"</string>
- <string name="handle_text" msgid="1766582106752184456">"Handle"</string>
+ <string name="handle_text" msgid="4419667835599523257">"App handle"</string>
<string name="app_icon_text" msgid="2823268023931811747">"App icon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Full screen"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktop mode"</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
index c17b9f7a..71701c9 100644
--- a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimise"</string>
<string name="close_button_text" msgid="2913281996024033299">"Close"</string>
<string name="back_button_text" msgid="1469718707134137085">"Back"</string>
- <string name="handle_text" msgid="1766582106752184456">"Handle"</string>
+ <string name="handle_text" msgid="4419667835599523257">"App handle"</string>
<string name="app_icon_text" msgid="2823268023931811747">"App icon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Full screen"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktop mode"</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
index 3503080..42d5f06 100644
--- a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimize"</string>
<string name="close_button_text" msgid="2913281996024033299">"Close"</string>
<string name="back_button_text" msgid="1469718707134137085">"Back"</string>
- <string name="handle_text" msgid="1766582106752184456">"Handle"</string>
+ <string name="handle_text" msgid="4419667835599523257">"App handle"</string>
<string name="app_icon_text" msgid="2823268023931811747">"App Icon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Fullscreen"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktop Mode"</string>
diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
index 049649f..1e30912 100644
--- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string>
<string name="close_button_text" msgid="2913281996024033299">"Cerrar"</string>
<string name="back_button_text" msgid="1469718707134137085">"Atrás"</string>
- <string name="handle_text" msgid="1766582106752184456">"Controlador"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Controlador de la app"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Ícono de la app"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modo de escritorio"</string>
diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml
index 7741318..312e297 100644
--- a/libs/WindowManager/Shell/res/values-es/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string>
<string name="close_button_text" msgid="2913281996024033299">"Cerrar"</string>
<string name="back_button_text" msgid="1469718707134137085">"Atrás"</string>
- <string name="handle_text" msgid="1766582106752184456">"Controlador"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Controlador de la aplicación"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Icono de la aplicación"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modo Escritorio"</string>
diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml
index 29fc150..5e4ef81 100644
--- a/libs/WindowManager/Shell/res/values-et/strings.xml
+++ b/libs/WindowManager/Shell/res/values-et/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimeeri"</string>
<string name="close_button_text" msgid="2913281996024033299">"Sule"</string>
<string name="back_button_text" msgid="1469718707134137085">"Tagasi"</string>
- <string name="handle_text" msgid="1766582106752184456">"Käepide"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Rakenduse element"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Rakenduse ikoon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Täisekraan"</string>
<string name="desktop_text" msgid="1077633567027630454">"Lauaarvuti režiim"</string>
diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml
index 580f6e1..40d67a2 100644
--- a/libs/WindowManager/Shell/res/values-eu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-eu/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimizatu"</string>
<string name="close_button_text" msgid="2913281996024033299">"Itxi"</string>
<string name="back_button_text" msgid="1469718707134137085">"Atzera"</string>
- <string name="handle_text" msgid="1766582106752184456">"Kontu-izena"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Aplikazioaren kontrol-puntua"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Aplikazioaren ikonoa"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pantaila osoa"</string>
<string name="desktop_text" msgid="1077633567027630454">"Ordenagailuetarako modua"</string>
diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml
index 766e787..55da319 100644
--- a/libs/WindowManager/Shell/res/values-fa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fa/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"کوچک کردن"</string>
<string name="close_button_text" msgid="2913281996024033299">"بستن"</string>
<string name="back_button_text" msgid="1469718707134137085">"برگشتن"</string>
- <string name="handle_text" msgid="1766582106752184456">"دستگیره"</string>
+ <string name="handle_text" msgid="4419667835599523257">"دستگیره برنامه"</string>
<string name="app_icon_text" msgid="2823268023931811747">"نماد برنامه"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"تمامصفحه"</string>
<string name="desktop_text" msgid="1077633567027630454">"حالت رایانه"</string>
diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml
index 96c7b75..c2610ff 100644
--- a/libs/WindowManager/Shell/res/values-fi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fi/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Pienennä"</string>
<string name="close_button_text" msgid="2913281996024033299">"Sulje"</string>
<string name="back_button_text" msgid="1469718707134137085">"Takaisin"</string>
- <string name="handle_text" msgid="1766582106752184456">"Kahva"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Sovelluksen tunnus"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Sovelluskuvake"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Koko näyttö"</string>
<string name="desktop_text" msgid="1077633567027630454">"Työpöytätila"</string>
diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
index e54e59d..7a59b62 100644
--- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Réduire"</string>
<string name="close_button_text" msgid="2913281996024033299">"Fermer"</string>
<string name="back_button_text" msgid="1469718707134137085">"Retour"</string>
- <string name="handle_text" msgid="1766582106752184456">"Identifiant"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Poignée de l\'appli"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Icône de l\'appli"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Plein écran"</string>
<string name="desktop_text" msgid="1077633567027630454">"Mode Bureau"</string>
diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml
index d150ad7..0cf944f 100644
--- a/libs/WindowManager/Shell/res/values-fr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Réduire"</string>
<string name="close_button_text" msgid="2913281996024033299">"Fermer"</string>
<string name="back_button_text" msgid="1469718707134137085">"Retour"</string>
- <string name="handle_text" msgid="1766582106752184456">"Poignée"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Poignée de l\'appli"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Icône d\'application"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Plein écran"</string>
<string name="desktop_text" msgid="1077633567027630454">"Mode ordinateur"</string>
diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml
index 6429fb3..0f2a601 100644
--- a/libs/WindowManager/Shell/res/values-gl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gl/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string>
<string name="close_button_text" msgid="2913281996024033299">"Pechar"</string>
<string name="back_button_text" msgid="1469718707134137085">"Atrás"</string>
- <string name="handle_text" msgid="1766582106752184456">"Controlador"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Controlador da aplicación"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Icona de aplicación"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modo de escritorio"</string>
diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml
index f8bdfae..6151da0 100644
--- a/libs/WindowManager/Shell/res/values-gu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gu/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"નાનું કરો"</string>
<string name="close_button_text" msgid="2913281996024033299">"બંધ કરો"</string>
<string name="back_button_text" msgid="1469718707134137085">"પાછળ"</string>
- <string name="handle_text" msgid="1766582106752184456">"હૅન્ડલ"</string>
+ <string name="handle_text" msgid="4419667835599523257">"ઍપનું હૅન્ડલ"</string>
<string name="app_icon_text" msgid="2823268023931811747">"ઍપનું આઇકન"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"પૂર્ણસ્ક્રીન"</string>
<string name="desktop_text" msgid="1077633567027630454">"ડેસ્કટૉપ મોડ"</string>
diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml
index d7c3803..04e76bc 100644
--- a/libs/WindowManager/Shell/res/values-hi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hi/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"विंडो छोटी करें"</string>
<string name="close_button_text" msgid="2913281996024033299">"बंद करें"</string>
<string name="back_button_text" msgid="1469718707134137085">"वापस जाएं"</string>
- <string name="handle_text" msgid="1766582106752184456">"हैंडल"</string>
+ <string name="handle_text" msgid="4419667835599523257">"ऐप्लिकेशन का हैंडल"</string>
<string name="app_icon_text" msgid="2823268023931811747">"ऐप्लिकेशन आइकॉन"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"फ़ुलस्क्रीन"</string>
<string name="desktop_text" msgid="1077633567027630454">"डेस्कटॉप मोड"</string>
diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml
index 000b0e6..aa2ee17 100644
--- a/libs/WindowManager/Shell/res/values-hr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hr/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimiziraj"</string>
<string name="close_button_text" msgid="2913281996024033299">"Zatvori"</string>
<string name="back_button_text" msgid="1469718707134137085">"Natrag"</string>
- <string name="handle_text" msgid="1766582106752184456">"Pokazivač"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Pokazivač aplikacije"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikacije"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Puni zaslon"</string>
<string name="desktop_text" msgid="1077633567027630454">"Stolni način rada"</string>
diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml
index b1268cc..8ffeeed 100644
--- a/libs/WindowManager/Shell/res/values-hu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hu/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Kis méret"</string>
<string name="close_button_text" msgid="2913281996024033299">"Bezárás"</string>
<string name="back_button_text" msgid="1469718707134137085">"Vissza"</string>
- <string name="handle_text" msgid="1766582106752184456">"Fogópont"</string>
+ <string name="handle_text" msgid="4419667835599523257">"App fogópontja"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Alkalmazásikon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Teljes képernyő"</string>
<string name="desktop_text" msgid="1077633567027630454">"Asztali üzemmód"</string>
diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml
index 1d2d2ff..b3fccfa 100644
--- a/libs/WindowManager/Shell/res/values-hy/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hy/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Ծալել"</string>
<string name="close_button_text" msgid="2913281996024033299">"Փակել"</string>
<string name="back_button_text" msgid="1469718707134137085">"Հետ"</string>
- <string name="handle_text" msgid="1766582106752184456">"Նշիչ"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Հավելվածի կեղծանուն"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Հավելվածի պատկերակ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Լիաէկրան"</string>
<string name="desktop_text" msgid="1077633567027630454">"Համակարգչի ռեժիմ"</string>
diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml
index 17e91050..38b24f9 100644
--- a/libs/WindowManager/Shell/res/values-in/strings.xml
+++ b/libs/WindowManager/Shell/res/values-in/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimalkan"</string>
<string name="close_button_text" msgid="2913281996024033299">"Tutup"</string>
<string name="back_button_text" msgid="1469718707134137085">"Kembali"</string>
- <string name="handle_text" msgid="1766582106752184456">"Tuas"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Penanganan aplikasi"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Ikon Aplikasi"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Layar Penuh"</string>
<string name="desktop_text" msgid="1077633567027630454">"Mode Desktop"</string>
diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml
index b955ef8..5b1f4d2 100644
--- a/libs/WindowManager/Shell/res/values-is/strings.xml
+++ b/libs/WindowManager/Shell/res/values-is/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minnka"</string>
<string name="close_button_text" msgid="2913281996024033299">"Loka"</string>
<string name="back_button_text" msgid="1469718707134137085">"Til baka"</string>
- <string name="handle_text" msgid="1766582106752184456">"Handfang"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Handfang forrits"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Tákn forrits"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Allur skjárinn"</string>
<string name="desktop_text" msgid="1077633567027630454">"Skjáborðsstilling"</string>
diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml
index d33e770..adc9569 100644
--- a/libs/WindowManager/Shell/res/values-it/strings.xml
+++ b/libs/WindowManager/Shell/res/values-it/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Riduci a icona"</string>
<string name="close_button_text" msgid="2913281996024033299">"Chiudi"</string>
<string name="back_button_text" msgid="1469718707134137085">"Indietro"</string>
- <string name="handle_text" msgid="1766582106752184456">"Handle"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Punto di manipolazione app"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Icona dell\'app"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Schermo intero"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modalità desktop"</string>
diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml
index 6ebbc81..9bae1c9 100644
--- a/libs/WindowManager/Shell/res/values-iw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-iw/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"מזעור"</string>
<string name="close_button_text" msgid="2913281996024033299">"סגירה"</string>
<string name="back_button_text" msgid="1469718707134137085">"חזרה"</string>
- <string name="handle_text" msgid="1766582106752184456">"נקודת אחיזה"</string>
+ <string name="handle_text" msgid="4419667835599523257">"נקודת אחיזה לאפליקציה"</string>
<string name="app_icon_text" msgid="2823268023931811747">"סמל האפליקציה"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"מסך מלא"</string>
<string name="desktop_text" msgid="1077633567027630454">"ממשק המחשב"</string>
diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml
index 55fd8b1..fff794e 100644
--- a/libs/WindowManager/Shell/res/values-ja/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ja/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"最小化"</string>
<string name="close_button_text" msgid="2913281996024033299">"閉じる"</string>
<string name="back_button_text" msgid="1469718707134137085">"戻る"</string>
- <string name="handle_text" msgid="1766582106752184456">"ハンドル"</string>
+ <string name="handle_text" msgid="4419667835599523257">"アプリハンドル"</string>
<string name="app_icon_text" msgid="2823268023931811747">"アプリのアイコン"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"全画面表示"</string>
<string name="desktop_text" msgid="1077633567027630454">"デスクトップ モード"</string>
diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml
index 2354208..a73c4f0 100644
--- a/libs/WindowManager/Shell/res/values-ka/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ka/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"ჩაკეცვა"</string>
<string name="close_button_text" msgid="2913281996024033299">"დახურვა"</string>
<string name="back_button_text" msgid="1469718707134137085">"უკან"</string>
- <string name="handle_text" msgid="1766582106752184456">"იდენტიფიკატორი"</string>
+ <string name="handle_text" msgid="4419667835599523257">"აპის იდენტიფიკატორი"</string>
<string name="app_icon_text" msgid="2823268023931811747">"აპის ხატულა"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"სრულ ეკრანზე"</string>
<string name="desktop_text" msgid="1077633567027630454">"დესკტოპის რეჟიმი"</string>
diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml
index 3e9b85e..5a7197e 100644
--- a/libs/WindowManager/Shell/res/values-kk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kk/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Кішірейту"</string>
<string name="close_button_text" msgid="2913281996024033299">"Жабу"</string>
<string name="back_button_text" msgid="1469718707134137085">"Артқа"</string>
- <string name="handle_text" msgid="1766582106752184456">"Идентификатор"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Қолданба идентификаторы"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Қолданба белгішесі"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Толық экран"</string>
<string name="desktop_text" msgid="1077633567027630454">"Компьютер режимі"</string>
diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml
index 69c0e1e..4db7aea 100644
--- a/libs/WindowManager/Shell/res/values-km/strings.xml
+++ b/libs/WindowManager/Shell/res/values-km/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"បង្រួម"</string>
<string name="close_button_text" msgid="2913281996024033299">"បិទ"</string>
<string name="back_button_text" msgid="1469718707134137085">"ថយក្រោយ"</string>
- <string name="handle_text" msgid="1766582106752184456">"ឈ្មោះអ្នកប្រើប្រាស់"</string>
+ <string name="handle_text" msgid="4419667835599523257">"ឈ្មោះអ្នកប្រើប្រាស់កម្មវិធី"</string>
<string name="app_icon_text" msgid="2823268023931811747">"រូបកម្មវិធី"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"អេក្រង់ពេញ"</string>
<string name="desktop_text" msgid="1077633567027630454">"មុខងារកុំព្យូទ័រ"</string>
diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml
index 88a29df..5615afc 100644
--- a/libs/WindowManager/Shell/res/values-kn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kn/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"ಕುಗ್ಗಿಸಿ"</string>
<string name="close_button_text" msgid="2913281996024033299">"ಮುಚ್ಚಿರಿ"</string>
<string name="back_button_text" msgid="1469718707134137085">"ಹಿಂದಕ್ಕೆ"</string>
- <string name="handle_text" msgid="1766582106752184456">"ಹ್ಯಾಂಡಲ್"</string>
+ <string name="handle_text" msgid="4419667835599523257">"ಆ್ಯಪ್ ಹ್ಯಾಂಡಲ್"</string>
<string name="app_icon_text" msgid="2823268023931811747">"ಆ್ಯಪ್ ಐಕಾನ್"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ಫುಲ್ಸ್ಕ್ರೀನ್"</string>
<string name="desktop_text" msgid="1077633567027630454">"ಡೆಸ್ಕ್ಟಾಪ್ ಮೋಡ್"</string>
diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml
index 0f27080d..33b980d 100644
--- a/libs/WindowManager/Shell/res/values-ko/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ko/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"최소화"</string>
<string name="close_button_text" msgid="2913281996024033299">"닫기"</string>
<string name="back_button_text" msgid="1469718707134137085">"뒤로"</string>
- <string name="handle_text" msgid="1766582106752184456">"핸들"</string>
+ <string name="handle_text" msgid="4419667835599523257">"앱 핸들"</string>
<string name="app_icon_text" msgid="2823268023931811747">"앱 아이콘"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"전체 화면"</string>
<string name="desktop_text" msgid="1077633567027630454">"데스크톱 모드"</string>
diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml
index 289d930..bf3ca52 100644
--- a/libs/WindowManager/Shell/res/values-ky/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ky/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Кичирейтүү"</string>
<string name="close_button_text" msgid="2913281996024033299">"Жабуу"</string>
<string name="back_button_text" msgid="1469718707134137085">"Артка"</string>
- <string name="handle_text" msgid="1766582106752184456">"Маркер"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Колдонмонун маркери"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Колдонмонун сүрөтчөсү"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Толук экран"</string>
<string name="desktop_text" msgid="1077633567027630454">"Компьютер режими"</string>
diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml
index 0b84d2c..ac6fa00 100644
--- a/libs/WindowManager/Shell/res/values-lo/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lo/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"ຫຍໍ້ລົງ"</string>
<string name="close_button_text" msgid="2913281996024033299">"ປິດ"</string>
<string name="back_button_text" msgid="1469718707134137085">"ກັບຄືນ"</string>
- <string name="handle_text" msgid="1766582106752184456">"ມືບັງຄັບ"</string>
+ <string name="handle_text" msgid="4419667835599523257">"ຊື່ຜູ້ໃຊ້ແອັບ"</string>
<string name="app_icon_text" msgid="2823268023931811747">"ໄອຄອນແອັບ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ເຕັມຈໍ"</string>
<string name="desktop_text" msgid="1077633567027630454">"ໂໝດເດັສທັອບ"</string>
diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml
index 21dbb68..97b53d3 100644
--- a/libs/WindowManager/Shell/res/values-lt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lt/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Sumažinti"</string>
<string name="close_button_text" msgid="2913281996024033299">"Uždaryti"</string>
<string name="back_button_text" msgid="1469718707134137085">"Atgal"</string>
- <string name="handle_text" msgid="1766582106752184456">"Rankenėlė"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Programos kreipinys"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Programos piktograma"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Visas ekranas"</string>
<string name="desktop_text" msgid="1077633567027630454">"Stalinio kompiuterio režimas"</string>
diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml
index f988c14..3a7e90a 100644
--- a/libs/WindowManager/Shell/res/values-lv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lv/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimizēt"</string>
<string name="close_button_text" msgid="2913281996024033299">"Aizvērt"</string>
<string name="back_button_text" msgid="1469718707134137085">"Atpakaļ"</string>
- <string name="handle_text" msgid="1766582106752184456">"Turis"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Lietotnes turis"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Lietotnes ikona"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pilnekrāna režīms"</string>
<string name="desktop_text" msgid="1077633567027630454">"Darbvirsmas režīms"</string>
diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml
index ce34b97..f7867ce 100644
--- a/libs/WindowManager/Shell/res/values-mk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mk/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Минимизирај"</string>
<string name="close_button_text" msgid="2913281996024033299">"Затвори"</string>
<string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
- <string name="handle_text" msgid="1766582106752184456">"Прекар"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Прекар на апликацијата"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Икона на апликацијата"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Цел екран"</string>
<string name="desktop_text" msgid="1077633567027630454">"Режим за компјутер"</string>
diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml
index 2efd983..68ff074 100644
--- a/libs/WindowManager/Shell/res/values-ml/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ml/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"ചെറുതാക്കുക"</string>
<string name="close_button_text" msgid="2913281996024033299">"അടയ്ക്കുക"</string>
<string name="back_button_text" msgid="1469718707134137085">"മടങ്ങുക"</string>
- <string name="handle_text" msgid="1766582106752184456">"ഹാൻഡിൽ"</string>
+ <string name="handle_text" msgid="4419667835599523257">"ആപ്പ് ഹാൻഡിൽ"</string>
<string name="app_icon_text" msgid="2823268023931811747">"ആപ്പ് ഐക്കൺ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"പൂർണ്ണസ്ക്രീൻ"</string>
<string name="desktop_text" msgid="1077633567027630454">"ഡെസ്ക്ടോപ്പ് മോഡ്"</string>
diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml
index de58ed8..27b38bc 100644
--- a/libs/WindowManager/Shell/res/values-mn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mn/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Багасгах"</string>
<string name="close_button_text" msgid="2913281996024033299">"Хаах"</string>
<string name="back_button_text" msgid="1469718707134137085">"Буцах"</string>
- <string name="handle_text" msgid="1766582106752184456">"Бариул"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Аппын бариул"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Aппын дүрс тэмдэг"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Бүтэн дэлгэц"</string>
<string name="desktop_text" msgid="1077633567027630454">"Дэлгэцийн горим"</string>
diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml
index ef71e86..f57f063 100644
--- a/libs/WindowManager/Shell/res/values-mr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mr/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"लहान करा"</string>
<string name="close_button_text" msgid="2913281996024033299">"बंद करा"</string>
<string name="back_button_text" msgid="1469718707134137085">"मागे जा"</string>
- <string name="handle_text" msgid="1766582106752184456">"हँडल"</string>
+ <string name="handle_text" msgid="4419667835599523257">"अॅपचे हँडल"</string>
<string name="app_icon_text" msgid="2823268023931811747">"अॅप आयकन"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"फुलस्क्रीन"</string>
<string name="desktop_text" msgid="1077633567027630454">"डेस्कटॉप मोड"</string>
diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml
index a9a97d8..9c3b871 100644
--- a/libs/WindowManager/Shell/res/values-ms/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ms/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimumkan"</string>
<string name="close_button_text" msgid="2913281996024033299">"Tutup"</string>
<string name="back_button_text" msgid="1469718707134137085">"Kembali"</string>
- <string name="handle_text" msgid="1766582106752184456">"Pemegang"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Pengendalian apl"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Ikon Apl"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Skrin penuh"</string>
<string name="desktop_text" msgid="1077633567027630454">"Mod Desktop"</string>
diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml
index 2f313cf..2685c56 100644
--- a/libs/WindowManager/Shell/res/values-my/strings.xml
+++ b/libs/WindowManager/Shell/res/values-my/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"ချုံ့ရန်"</string>
<string name="close_button_text" msgid="2913281996024033299">"ပိတ်ရန်"</string>
<string name="back_button_text" msgid="1469718707134137085">"နောက်သို့"</string>
- <string name="handle_text" msgid="1766582106752184456">"သုံးသူအမည်"</string>
+ <string name="handle_text" msgid="4419667835599523257">"အက်ပ်သုံးသူအမည်"</string>
<string name="app_icon_text" msgid="2823268023931811747">"အက်ပ်သင်္ကေတ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ဖန်သားပြင်အပြည့်"</string>
<string name="desktop_text" msgid="1077633567027630454">"ဒက်စ်တော့မုဒ်"</string>
diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml
index 11a807b..36c0b8b 100644
--- a/libs/WindowManager/Shell/res/values-nb/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nb/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimer"</string>
<string name="close_button_text" msgid="2913281996024033299">"Lukk"</string>
<string name="back_button_text" msgid="1469718707134137085">"Tilbake"</string>
- <string name="handle_text" msgid="1766582106752184456">"Håndtak"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Apphåndtak"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Appikon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Fullskjerm"</string>
<string name="desktop_text" msgid="1077633567027630454">"Skrivebordmodus"</string>
diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml
index 7cc4a43..4e96f5f5 100644
--- a/libs/WindowManager/Shell/res/values-ne/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ne/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"मिनिमाइज गर्नुहोस्"</string>
<string name="close_button_text" msgid="2913281996024033299">"बन्द गर्नुहोस्"</string>
<string name="back_button_text" msgid="1469718707134137085">"पछाडि"</string>
- <string name="handle_text" msgid="1766582106752184456">"ह्यान्डल"</string>
+ <string name="handle_text" msgid="4419667835599523257">"एपको ह्यान्डल"</string>
<string name="app_icon_text" msgid="2823268023931811747">"एपको आइकन"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"फुल स्क्रिन"</string>
<string name="desktop_text" msgid="1077633567027630454">"डेस्कटप मोड"</string>
diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml
index 7480add..5ae084a 100644
--- a/libs/WindowManager/Shell/res/values-nl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nl/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimaliseren"</string>
<string name="close_button_text" msgid="2913281996024033299">"Sluiten"</string>
<string name="back_button_text" msgid="1469718707134137085">"Terug"</string>
- <string name="handle_text" msgid="1766582106752184456">"Gebruikersnaam"</string>
+ <string name="handle_text" msgid="4419667835599523257">"App-handgreep"</string>
<string name="app_icon_text" msgid="2823268023931811747">"App-icoon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Volledig scherm"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktopmodus"</string>
diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml
index b3b5e7c..536c6fe 100644
--- a/libs/WindowManager/Shell/res/values-or/strings.xml
+++ b/libs/WindowManager/Shell/res/values-or/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"ଛୋଟ କରନ୍ତୁ"</string>
<string name="close_button_text" msgid="2913281996024033299">"ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="back_button_text" msgid="1469718707134137085">"ପଛକୁ ଫେରନ୍ତୁ"</string>
- <string name="handle_text" msgid="1766582106752184456">"ହେଣ୍ଡେଲ"</string>
+ <string name="handle_text" msgid="4419667835599523257">"ଆପର ହେଣ୍ଡେଲ"</string>
<string name="app_icon_text" msgid="2823268023931811747">"ଆପ ଆଇକନ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ପୂର୍ଣ୍ଣସ୍କ୍ରିନ"</string>
<string name="desktop_text" msgid="1077633567027630454">"ଡେସ୍କଟପ ମୋଡ"</string>
diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml
index 4a08f67..bdef224 100644
--- a/libs/WindowManager/Shell/res/values-pa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pa/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"ਛੋਟਾ ਕਰੋ"</string>
<string name="close_button_text" msgid="2913281996024033299">"ਬੰਦ ਕਰੋ"</string>
<string name="back_button_text" msgid="1469718707134137085">"ਪਿੱਛੇ"</string>
- <string name="handle_text" msgid="1766582106752184456">"ਹੈਂਡਲ"</string>
+ <string name="handle_text" msgid="4419667835599523257">"ਐਪ ਹੈਂਡਲ"</string>
<string name="app_icon_text" msgid="2823268023931811747">"ਐਪ ਪ੍ਰਤੀਕ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ਪੂਰੀ-ਸਕ੍ਰੀਨ"</string>
<string name="desktop_text" msgid="1077633567027630454">"ਡੈਸਕਟਾਪ ਮੋਡ"</string>
diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml
index 1c268bd..41c4bb0 100644
--- a/libs/WindowManager/Shell/res/values-pl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pl/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimalizuj"</string>
<string name="close_button_text" msgid="2913281996024033299">"Zamknij"</string>
<string name="back_button_text" msgid="1469718707134137085">"Wstecz"</string>
- <string name="handle_text" msgid="1766582106752184456">"Uchwyt"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Uchwyt aplikacji"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikacji"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pełny ekran"</string>
<string name="desktop_text" msgid="1077633567027630454">"Tryb pulpitu"</string>
diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
index 82566fe..83d34c0 100644
--- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string>
<string name="close_button_text" msgid="2913281996024033299">"Fechar"</string>
<string name="back_button_text" msgid="1469718707134137085">"Voltar"</string>
- <string name="handle_text" msgid="1766582106752184456">"Alça"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Identificador do app"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Ícone do app"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Tela cheia"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modo área de trabalho"</string>
diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
index b2e8918..425ad05 100644
--- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string>
<string name="close_button_text" msgid="2913281996024033299">"Fechar"</string>
<string name="back_button_text" msgid="1469718707134137085">"Anterior"</string>
- <string name="handle_text" msgid="1766582106752184456">"Indicador"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Indicador da app"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Ícone da app"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Ecrã inteiro"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modo de ambiente de trabalho"</string>
diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml
index 82566fe..83d34c0 100644
--- a/libs/WindowManager/Shell/res/values-pt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string>
<string name="close_button_text" msgid="2913281996024033299">"Fechar"</string>
<string name="back_button_text" msgid="1469718707134137085">"Voltar"</string>
- <string name="handle_text" msgid="1766582106752184456">"Alça"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Identificador do app"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Ícone do app"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Tela cheia"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modo área de trabalho"</string>
diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml
index 503f68c..ea1a6b7 100644
--- a/libs/WindowManager/Shell/res/values-ro/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ro/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimizează"</string>
<string name="close_button_text" msgid="2913281996024033299">"Închide"</string>
<string name="back_button_text" msgid="1469718707134137085">"Înapoi"</string>
- <string name="handle_text" msgid="1766582106752184456">"Ghidaj"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Handle de aplicație"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Pictograma aplicației"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Ecran complet"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modul desktop"</string>
diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml
index b2a6030..d0292be 100644
--- a/libs/WindowManager/Shell/res/values-ru/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ru/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Свернуть"</string>
<string name="close_button_text" msgid="2913281996024033299">"Закрыть"</string>
<string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
- <string name="handle_text" msgid="1766582106752184456">"Маркер"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Обозначение приложения"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Значок приложения"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Полноэкранный режим"</string>
<string name="desktop_text" msgid="1077633567027630454">"Режим компьютера"</string>
diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml
index 8589f42..7994222 100644
--- a/libs/WindowManager/Shell/res/values-si/strings.xml
+++ b/libs/WindowManager/Shell/res/values-si/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"කුඩා කරන්න"</string>
<string name="close_button_text" msgid="2913281996024033299">"වසන්න"</string>
<string name="back_button_text" msgid="1469718707134137085">"ආපසු"</string>
- <string name="handle_text" msgid="1766582106752184456">"හැඬලය"</string>
+ <string name="handle_text" msgid="4419667835599523257">"යෙදුම් හසුරුව"</string>
<string name="app_icon_text" msgid="2823268023931811747">"යෙදුම් නිරූපකය"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"පූර්ණ තිරය"</string>
<string name="desktop_text" msgid="1077633567027630454">"ඩෙස්ක්ටොප් ප්රකාරය"</string>
diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml
index 8959744..896a85b 100644
--- a/libs/WindowManager/Shell/res/values-sk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sk/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimalizovať"</string>
<string name="close_button_text" msgid="2913281996024033299">"Zavrieť"</string>
<string name="back_button_text" msgid="1469718707134137085">"Späť"</string>
- <string name="handle_text" msgid="1766582106752184456">"Rukoväť"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Rukoväť aplikácie"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikácie"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Celá obrazovka"</string>
<string name="desktop_text" msgid="1077633567027630454">"Režim počítača"</string>
diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml
index 5848f92..3418c48 100644
--- a/libs/WindowManager/Shell/res/values-sl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sl/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimiraj"</string>
<string name="close_button_text" msgid="2913281996024033299">"Zapri"</string>
<string name="back_button_text" msgid="1469718707134137085">"Nazaj"</string>
- <string name="handle_text" msgid="1766582106752184456">"Ročica"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Identifikator aplikacije"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikacije"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Celozaslonsko"</string>
<string name="desktop_text" msgid="1077633567027630454">"Namizni način"</string>
diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml
index 4063894..306fcaa 100644
--- a/libs/WindowManager/Shell/res/values-sq/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sq/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimizo"</string>
<string name="close_button_text" msgid="2913281996024033299">"Mbyll"</string>
<string name="back_button_text" msgid="1469718707134137085">"Pas"</string>
- <string name="handle_text" msgid="1766582106752184456">"Emërtimi"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Emërtimi i aplikacionit"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Ikona e aplikacionit"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Ekrani i plotë"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modaliteti i desktopit"</string>
diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml
index 8402eef..8fd824e 100644
--- a/libs/WindowManager/Shell/res/values-sr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sr/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Умањите"</string>
<string name="close_button_text" msgid="2913281996024033299">"Затворите"</string>
<string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
- <string name="handle_text" msgid="1766582106752184456">"Идентификатор"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Идентификатор апликације"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Икона апликације"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Преко целог екрана"</string>
<string name="desktop_text" msgid="1077633567027630454">"Режим за рачунаре"</string>
diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml
index 77c7d09..b6375c6 100644
--- a/libs/WindowManager/Shell/res/values-sv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sv/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Minimera"</string>
<string name="close_button_text" msgid="2913281996024033299">"Stäng"</string>
<string name="back_button_text" msgid="1469718707134137085">"Tillbaka"</string>
- <string name="handle_text" msgid="1766582106752184456">"Handtag"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Apphandtag"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Appikon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Helskärm"</string>
<string name="desktop_text" msgid="1077633567027630454">"Datorläge"</string>
diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml
index d367c80..2eadf34 100644
--- a/libs/WindowManager/Shell/res/values-sw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sw/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Punguza"</string>
<string name="close_button_text" msgid="2913281996024033299">"Funga"</string>
<string name="back_button_text" msgid="1469718707134137085">"Rudi nyuma"</string>
- <string name="handle_text" msgid="1766582106752184456">"Ncha"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Utambulisho wa programu"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Aikoni ya Programu"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Skrini nzima"</string>
<string name="desktop_text" msgid="1077633567027630454">"Hali ya Kompyuta ya mezani"</string>
diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml
index 697f951..36f69ce 100644
--- a/libs/WindowManager/Shell/res/values-ta/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ta/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"சிறிதாக்கும்"</string>
<string name="close_button_text" msgid="2913281996024033299">"மூடும்"</string>
<string name="back_button_text" msgid="1469718707134137085">"பின்செல்லும்"</string>
- <string name="handle_text" msgid="1766582106752184456">"ஹேண்டில்"</string>
+ <string name="handle_text" msgid="4419667835599523257">"ஆப்ஸ் ஹேண்டில்"</string>
<string name="app_icon_text" msgid="2823268023931811747">"ஆப்ஸ் ஐகான்"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"முழுத்திரை"</string>
<string name="desktop_text" msgid="1077633567027630454">"டெஸ்க்டாப் பயன்முறை"</string>
diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml
index ef094fc..2446ae8 100644
--- a/libs/WindowManager/Shell/res/values-te/strings.xml
+++ b/libs/WindowManager/Shell/res/values-te/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"కుదించండి"</string>
<string name="close_button_text" msgid="2913281996024033299">"మూసివేయండి"</string>
<string name="back_button_text" msgid="1469718707134137085">"వెనుకకు"</string>
- <string name="handle_text" msgid="1766582106752184456">"హ్యాండిల్"</string>
+ <string name="handle_text" msgid="4419667835599523257">"యాప్ హ్యాండిల్"</string>
<string name="app_icon_text" msgid="2823268023931811747">"యాప్ చిహ్నం"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ఫుల్-స్క్రీన్"</string>
<string name="desktop_text" msgid="1077633567027630454">"డెస్క్టాప్ మోడ్"</string>
diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml
index 762a81a..10cf216 100644
--- a/libs/WindowManager/Shell/res/values-th/strings.xml
+++ b/libs/WindowManager/Shell/res/values-th/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"ย่อ"</string>
<string name="close_button_text" msgid="2913281996024033299">"ปิด"</string>
<string name="back_button_text" msgid="1469718707134137085">"กลับ"</string>
- <string name="handle_text" msgid="1766582106752184456">"แฮนเดิล"</string>
+ <string name="handle_text" msgid="4419667835599523257">"แฮนเดิลแอป"</string>
<string name="app_icon_text" msgid="2823268023931811747">"ไอคอนแอป"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"เต็มหน้าจอ"</string>
<string name="desktop_text" msgid="1077633567027630454">"โหมดเดสก์ท็อป"</string>
diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml
index 418f500..497ac56b 100644
--- a/libs/WindowManager/Shell/res/values-tl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tl/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"I-minimize"</string>
<string name="close_button_text" msgid="2913281996024033299">"Isara"</string>
<string name="back_button_text" msgid="1469718707134137085">"Bumalik"</string>
- <string name="handle_text" msgid="1766582106752184456">"Handle"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Handle ng app"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Icon ng App"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Fullscreen"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktop Mode"</string>
diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml
index 1a97240..05eb1ba 100644
--- a/libs/WindowManager/Shell/res/values-tr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tr/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Küçült"</string>
<string name="close_button_text" msgid="2913281996024033299">"Kapat"</string>
<string name="back_button_text" msgid="1469718707134137085">"Geri"</string>
- <string name="handle_text" msgid="1766582106752184456">"Herkese açık kullanıcı adı"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Uygulama tanıtıcısı"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Uygulama Simgesi"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Tam Ekran"</string>
<string name="desktop_text" msgid="1077633567027630454">"Masaüstü Modu"</string>
diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml
index a5fcae5..5c3cfaa 100644
--- a/libs/WindowManager/Shell/res/values-uk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uk/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Згорнути"</string>
<string name="close_button_text" msgid="2913281996024033299">"Закрити"</string>
<string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
- <string name="handle_text" msgid="1766582106752184456">"Маркер"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Дескриптор додатка"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Значок додатка"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"На весь екран"</string>
<string name="desktop_text" msgid="1077633567027630454">"Режим комп’ютера"</string>
diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml
index 2cf9f32..98c433b 100644
--- a/libs/WindowManager/Shell/res/values-ur/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ur/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"چھوٹا کریں"</string>
<string name="close_button_text" msgid="2913281996024033299">"بند کریں"</string>
<string name="back_button_text" msgid="1469718707134137085">"پیچھے"</string>
- <string name="handle_text" msgid="1766582106752184456">"ہینڈل"</string>
+ <string name="handle_text" msgid="4419667835599523257">"ایپ ہینڈل"</string>
<string name="app_icon_text" msgid="2823268023931811747">"ایپ کا آئیکن"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"مکمل اسکرین"</string>
<string name="desktop_text" msgid="1077633567027630454">"ڈیسک ٹاپ موڈ"</string>
diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml
index f8cd43f..3ec676d 100644
--- a/libs/WindowManager/Shell/res/values-uz/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uz/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Kichraytirish"</string>
<string name="close_button_text" msgid="2913281996024033299">"Yopish"</string>
<string name="back_button_text" msgid="1469718707134137085">"Orqaga"</string>
- <string name="handle_text" msgid="1766582106752184456">"Identifikator"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Ilova identifikatori"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Ilova belgisi"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Butun ekran"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktop rejimi"</string>
diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml
index 86e2b33..125d703 100644
--- a/libs/WindowManager/Shell/res/values-vi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-vi/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Thu nhỏ"</string>
<string name="close_button_text" msgid="2913281996024033299">"Đóng"</string>
<string name="back_button_text" msgid="1469718707134137085">"Quay lại"</string>
- <string name="handle_text" msgid="1766582106752184456">"Xử lý"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Ô điều khiển ứng dụng"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Biểu tượng ứng dụng"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Toàn màn hình"</string>
<string name="desktop_text" msgid="1077633567027630454">"Chế độ máy tính"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
index a56553b..6ccc38b 100644
--- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"最小化"</string>
<string name="close_button_text" msgid="2913281996024033299">"关闭"</string>
<string name="back_button_text" msgid="1469718707134137085">"返回"</string>
- <string name="handle_text" msgid="1766582106752184456">"处理"</string>
+ <string name="handle_text" msgid="4419667835599523257">"应用手柄"</string>
<string name="app_icon_text" msgid="2823268023931811747">"应用图标"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"全屏"</string>
<string name="desktop_text" msgid="1077633567027630454">"桌面模式"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
index 78c97e4..2787c1e 100644
--- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"最小化"</string>
<string name="close_button_text" msgid="2913281996024033299">"關閉"</string>
<string name="back_button_text" msgid="1469718707134137085">"返去"</string>
- <string name="handle_text" msgid="1766582106752184456">"控點"</string>
+ <string name="handle_text" msgid="4419667835599523257">"應用程式控點"</string>
<string name="app_icon_text" msgid="2823268023931811747">"應用程式圖示"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"全螢幕"</string>
<string name="desktop_text" msgid="1077633567027630454">"桌面模式"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
index 307dc9d..72050fb 100644
--- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"最小化"</string>
<string name="close_button_text" msgid="2913281996024033299">"關閉"</string>
<string name="back_button_text" msgid="1469718707134137085">"返回"</string>
- <string name="handle_text" msgid="1766582106752184456">"控點"</string>
+ <string name="handle_text" msgid="4419667835599523257">"應用程式控制代碼"</string>
<string name="app_icon_text" msgid="2823268023931811747">"應用程式圖示"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"全螢幕"</string>
<string name="desktop_text" msgid="1077633567027630454">"電腦模式"</string>
diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml
index ba3df30..ac62a7b 100644
--- a/libs/WindowManager/Shell/res/values-zu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zu/strings.xml
@@ -107,7 +107,7 @@
<string name="minimize_button_text" msgid="271592547935841753">"Nciphisa"</string>
<string name="close_button_text" msgid="2913281996024033299">"Vala"</string>
<string name="back_button_text" msgid="1469718707134137085">"Emuva"</string>
- <string name="handle_text" msgid="1766582106752184456">"Isibambo"</string>
+ <string name="handle_text" msgid="4419667835599523257">"Inkomba ye-App"</string>
<string name="app_icon_text" msgid="2823268023931811747">"Isithonjana Se-app"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Isikrini esigcwele"</string>
<string name="desktop_text" msgid="1077633567027630454">"Imodi Yedeskithophu"</string>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 606ebb4..e6807ac 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -296,9 +296,6 @@
<!-- The width of the compat hint. -->
<dimen name="compat_hint_width">188dp</dimen>
- <!-- The width of the camera compat hint. -->
- <dimen name="camera_compat_hint_width">143dp</dimen>
-
<!-- The corner radius of the letterbox education dialog. -->
<dimen name="letterbox_education_dialog_corner_radius">28dp</dimen>
@@ -500,7 +497,7 @@
<!-- The maximum height of the handle menu in desktop mode. Four pills (52dp each) plus 2dp
spacing between them plus 4dp top padding. -->
- <dimen name="desktop_mode_handle_menu_height">218dp</dimen>
+ <dimen name="desktop_mode_handle_menu_height">270dp</dimen>
<!-- The elevation set on the handle menu pills. -->
<dimen name="desktop_mode_handle_menu_pill_elevation">1dp</dimen>
@@ -511,8 +508,11 @@
<!-- The height of the handle menu's "Windowing" pill in desktop mode. -->
<dimen name="desktop_mode_handle_menu_windowing_pill_height">52dp</dimen>
- <!-- The height of the handle menu's "More Actions" pill in desktop mode. -->
- <dimen name="desktop_mode_handle_menu_more_actions_pill_height">52dp</dimen>
+ <!-- The maximum height of the handle menu's "New Window" button in desktop mode. -->
+ <dimen name="desktop_mode_handle_menu_new_window_height">52dp</dimen>
+
+ <!-- The maximum height of the handle menu's "Screenshot" button in desktop mode. -->
+ <dimen name="desktop_mode_handle_menu_screenshot_height">52dp</dimen>
<!-- The height of the handle menu's "Open in browser" pill in desktop mode. -->
<dimen name="desktop_mode_handle_menu_open_in_browser_pill_height">52dp</dimen>
diff --git a/libs/WindowManager/Shell/res/values/strings.xml b/libs/WindowManager/Shell/res/values/strings.xml
index 8669af3..0a8166f 100644
--- a/libs/WindowManager/Shell/res/values/strings.xml
+++ b/libs/WindowManager/Shell/res/values/strings.xml
@@ -282,6 +282,8 @@
<string name="screenshot_text">Screenshot</string>
<!-- Accessibility text for the handle menu open in browser button [CHAR LIMIT=NONE] -->
<string name="open_in_browser_text">Open in browser</string>
+ <!-- Accessibility text for the handle menu new window button [CHAR LIMIT=NONE] -->
+ <string name="new_window_text">New Window</string>
<!-- Accessibility text for the handle menu close button [CHAR LIMIT=NONE] -->
<string name="close_text">Close</string>
<!-- Accessibility text for the handle menu close menu button [CHAR LIMIT=NONE] -->
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeFlags.kt b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeFlags.kt
index 1304969..434885f 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeFlags.kt
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeFlags.kt
@@ -26,105 +26,113 @@
*
* The class computes whether a Desktop Windowing flag should be enabled by using the aconfig flag
* value and the developer option override state (if applicable).
- **/
+ */
enum class DesktopModeFlags(
// Function called to obtain aconfig flag value.
private val flagFunction: () -> Boolean,
// Whether the flag state should be affected by developer option.
private val shouldOverrideByDevOption: Boolean
) {
- // All desktop mode related flags will be added here
- DESKTOP_WINDOWING_MODE(Flags::enableDesktopWindowingMode, true),
- CASCADING_WINDOWS(Flags::enableCascadingWindows, true),
- WALLPAPER_ACTIVITY(Flags::enableDesktopWindowingWallpaperActivity, true),
- MODALS_POLICY(Flags::enableDesktopWindowingModalsPolicy, true),
- THEMED_APP_HEADERS(Flags::enableThemedAppHeaders, true),
- QUICK_SWITCH(Flags::enableDesktopWindowingQuickSwitch, true),
- APP_HEADER_WITH_TASK_DENSITY(Flags::enableAppHeaderWithTaskDensity, true),
- TASK_STACK_OBSERVER_IN_SHELL(Flags::enableTaskStackObserverInShell, true),
- SIZE_CONSTRAINTS(Flags::enableDesktopWindowingSizeConstraints, true),
- DYNAMIC_INITIAL_BOUNDS(Flags::enableWindowingDynamicInitialBounds, true),
- ENABLE_DESKTOP_WINDOWING_TASK_LIMIT(Flags::enableDesktopWindowingTaskLimit, true);
-
- /**
- * Determines state of flag based on the actual flag and desktop mode developer option overrides.
- */
- fun isEnabled(context: Context): Boolean =
- if (!Flags.showDesktopWindowingDevOption() ||
- !shouldOverrideByDevOption ||
- context.contentResolver == null) {
- flagFunction()
- } else {
- val shouldToggleBeEnabledByDefault = DesktopModeStatus.shouldDevOptionBeEnabledByDefault()
- when (getToggleOverride(context)) {
- ToggleOverride.OVERRIDE_UNSET -> flagFunction()
- // When toggle override matches its default state, don't override flags. This helps users
- // reset their feature overrides.
- ToggleOverride.OVERRIDE_OFF ->
- if (shouldToggleBeEnabledByDefault) false else flagFunction()
- ToggleOverride.OVERRIDE_ON -> if (shouldToggleBeEnabledByDefault) flagFunction() else true
- }
- }
-
- private fun getToggleOverride(context: Context): ToggleOverride {
- val override =
- cachedToggleOverride
- ?: run {
- val override = getToggleOverrideFromSystem(context)
- // Cache toggle override the first time we encounter context. Override does not change
- // with context, as context is just used to fetch Settings.Global
- cachedToggleOverride = override
- Log.d(TAG, "Toggle override initialized to: $override")
- override
- }
-
- return override
- }
-
- private fun getToggleOverrideFromSystem(context: Context): ToggleOverride =
- convertToToggleOverrideWithFallback(
- Settings.Global.getInt(
- context.contentResolver,
- Settings.Global.DEVELOPMENT_OVERRIDE_DESKTOP_MODE_FEATURES,
- ToggleOverride.OVERRIDE_UNSET.setting),
- ToggleOverride.OVERRIDE_UNSET)
-
- /**
- * Override state of desktop mode developer option toggle.
- *
- * @property setting The integer value that is associated with the developer option toggle
- * override
- */
- enum class ToggleOverride(val setting: Int) {
- /** No override is set. */
- OVERRIDE_UNSET(-1),
- /** Override to off. */
- OVERRIDE_OFF(0),
- /** Override to on. */
- OVERRIDE_ON(1)
- }
-
- companion object {
- private const val TAG = "DesktopModeFlags"
+ // All desktop mode related flags will be added here
+ DESKTOP_WINDOWING_MODE(Flags::enableDesktopWindowingMode, true),
+ CASCADING_WINDOWS(Flags::enableCascadingWindows, true),
+ WALLPAPER_ACTIVITY(Flags::enableDesktopWindowingWallpaperActivity, true),
+ MODALS_POLICY(Flags::enableDesktopWindowingModalsPolicy, true),
+ THEMED_APP_HEADERS(Flags::enableThemedAppHeaders, true),
+ QUICK_SWITCH(Flags::enableDesktopWindowingQuickSwitch, true),
+ APP_HEADER_WITH_TASK_DENSITY(Flags::enableAppHeaderWithTaskDensity, true),
+ TASK_STACK_OBSERVER_IN_SHELL(Flags::enableTaskStackObserverInShell, true),
+ SIZE_CONSTRAINTS(Flags::enableDesktopWindowingSizeConstraints, true),
+ DISABLE_SNAP_RESIZE(Flags::disableNonResizableAppSnapResizing, true),
+ DYNAMIC_INITIAL_BOUNDS(Flags::enableWindowingDynamicInitialBounds, true),
+ ENABLE_DESKTOP_WINDOWING_TASK_LIMIT(Flags::enableDesktopWindowingTaskLimit, true),
+ BACK_NAVIGATION(Flags::enableDesktopWindowingBackNavigation, true),
+ EDGE_DRAG_RESIZE(Flags::enableWindowingEdgeDragResize, true),
+ TASKBAR_RUNNING_APPS(Flags::enableDesktopWindowingTaskbarRunningApps, true);
/**
- * Local cache for toggle override, which is initialized once on its first access. It needs to
- * be refreshed only on reboots as overridden state is expected to take effect on reboots.
+ * Determines state of flag based on the actual flag and desktop mode developer option
+ * overrides.
*/
- private var cachedToggleOverride: ToggleOverride? = null
+ fun isEnabled(context: Context): Boolean =
+ if (!Flags.showDesktopWindowingDevOption() ||
+ !shouldOverrideByDevOption ||
+ context.contentResolver == null) {
+ flagFunction()
+ } else {
+ val shouldToggleBeEnabledByDefault =
+ DesktopModeStatus.shouldDevOptionBeEnabledByDefault()
+ when (getToggleOverride(context)) {
+ ToggleOverride.OVERRIDE_UNSET -> flagFunction()
+ // When toggle override matches its default state, don't override flags. This helps
+ // users reset their feature overrides.
+ ToggleOverride.OVERRIDE_OFF ->
+ if (shouldToggleBeEnabledByDefault) false else flagFunction()
+ ToggleOverride.OVERRIDE_ON ->
+ if (shouldToggleBeEnabledByDefault) flagFunction() else true
+ }
+ }
- private val settingToToggleOverrideMap = ToggleOverride.entries.associateBy { it.setting }
+ private fun getToggleOverride(context: Context): ToggleOverride {
+ val override =
+ cachedToggleOverride
+ ?: run {
+ val override = getToggleOverrideFromSystem(context)
+ // Cache toggle override the first time we encounter context. Override does not
+ // change with context, as context is just used to fetch Settings.Global
+ cachedToggleOverride = override
+ Log.d(TAG, "Toggle override initialized to: $override")
+ override
+ }
- @JvmStatic
- fun convertToToggleOverrideWithFallback(
- overrideInt: Int,
- fallbackOverride: ToggleOverride
- ): ToggleOverride {
- return settingToToggleOverrideMap[overrideInt]
- ?: run {
- Log.w(TAG, "Unknown toggleOverride int $overrideInt")
- fallbackOverride
- }
+ return override
}
- }
+
+ private fun getToggleOverrideFromSystem(context: Context): ToggleOverride =
+ convertToToggleOverrideWithFallback(
+ Settings.Global.getInt(
+ context.contentResolver,
+ Settings.Global.DEVELOPMENT_OVERRIDE_DESKTOP_MODE_FEATURES,
+ ToggleOverride.OVERRIDE_UNSET.setting),
+ ToggleOverride.OVERRIDE_UNSET)
+
+ /**
+ * Override state of desktop mode developer option toggle.
+ *
+ * @property setting The integer value that is associated with the developer option toggle
+ * override
+ */
+ enum class ToggleOverride(val setting: Int) {
+ /** No override is set. */
+ OVERRIDE_UNSET(-1),
+ /** Override to off. */
+ OVERRIDE_OFF(0),
+ /** Override to on. */
+ OVERRIDE_ON(1)
+ }
+
+ companion object {
+ private const val TAG = "DesktopModeFlags"
+
+ /**
+ * Local cache for toggle override, which is initialized once on its first access. It needs
+ * to be refreshed only on reboots as overridden state is expected to take effect on
+ * reboots.
+ */
+ private var cachedToggleOverride: ToggleOverride? = null
+
+ private val settingToToggleOverrideMap = ToggleOverride.entries.associateBy { it.setting }
+
+ @JvmStatic
+ fun convertToToggleOverrideWithFallback(
+ overrideInt: Int,
+ fallbackOverride: ToggleOverride
+ ): ToggleOverride {
+ return settingToToggleOverrideMap[overrideInt]
+ ?: run {
+ Log.w(TAG, "Unknown toggleOverride int $overrideInt")
+ fallbackOverride
+ }
+ }
+ }
}
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 f014e55..452d12a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -24,7 +24,6 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static com.android.wm.shell.compatui.impl.CompatUIEventsKt.CAMERA_CONTROL_STATE_UPDATE;
import static com.android.wm.shell.compatui.impl.CompatUIEventsKt.SIZE_COMPAT_RESTART_BUTTON_APPEARED;
import static com.android.wm.shell.compatui.impl.CompatUIEventsKt.SIZE_COMPAT_RESTART_BUTTON_CLICKED;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG;
@@ -61,7 +60,6 @@
import com.android.wm.shell.compatui.CompatUIController;
import com.android.wm.shell.compatui.api.CompatUIHandler;
import com.android.wm.shell.compatui.api.CompatUIInfo;
-import com.android.wm.shell.compatui.impl.CompatUIEvents.CameraControlStateUpdated;
import com.android.wm.shell.compatui.impl.CompatUIEvents.SizeCompatRestartButtonAppeared;
import com.android.wm.shell.compatui.impl.CompatUIEvents.SizeCompatRestartButtonClicked;
import com.android.wm.shell.recents.RecentTasksController;
@@ -265,9 +263,6 @@
case SIZE_COMPAT_RESTART_BUTTON_CLICKED:
onSizeCompatRestartButtonClicked(compatUIEvent.asType());
break;
- case CAMERA_CONTROL_STATE_UPDATE:
- onCameraControlStateUpdated(compatUIEvent.asType());
- break;
default:
}
@@ -690,6 +685,15 @@
return result;
}
+ /** Return list of {@link RunningTaskInfo}s on all the displays. */
+ public ArrayList<RunningTaskInfo> getRunningTasks() {
+ ArrayList<RunningTaskInfo> result = new ArrayList<>();
+ for (int i = 0; i < mTasks.size(); i++) {
+ result.add(mTasks.valueAt(i).getTaskInfo());
+ }
+ return result;
+ }
+
/** Gets running task by taskId. Returns {@code null} if no such task observed. */
@Nullable
public RunningTaskInfo getRunningTaskInfo(int taskId) {
@@ -808,21 +812,6 @@
restartTaskTopActivityProcessIfVisible(info.getTaskInfo().token);
}
- @VisibleForTesting
- void onCameraControlStateUpdated(@NonNull CameraControlStateUpdated compatUIEvent) {
- final int taskId = compatUIEvent.getTaskId();
- final int state = compatUIEvent.getState();
- final TaskAppearedInfo info;
- synchronized (mLock) {
- info = mTasks.get(taskId);
- }
- if (info == null) {
- return;
- }
- updateCameraCompatControlState(info.getTaskInfo().token, state);
- }
-
-
private void logSizeCompatRestartButtonEventReported(@NonNull TaskAppearedInfo info,
int event) {
ActivityInfo topActivityInfo = info.getTaskInfo().topActivityInfo;
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 86e0f14..8d30db6 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
@@ -146,11 +146,6 @@
/** To be overridden by subclasses to adjust the animation surface change. */
void onAnimationUpdateInner(@NonNull SurfaceControl.Transaction t) {
// Update the surface position and alpha.
- if (com.android.graphics.libgui.flags.Flags.edgeExtensionShader()
- && mAnimation.getExtensionEdges() != 0) {
- t.setEdgeExtensionEffect(mLeash, mAnimation.getExtensionEdges());
- }
-
mTransformation.getMatrix().postTranslate(mContentRelOffset.x, mContentRelOffset.y);
t.setMatrix(mLeash, mTransformation.getMatrix(), mMatrix);
t.setAlpha(mLeash, mTransformation.getAlpha());
@@ -170,7 +165,7 @@
if (!cropRect.intersect(mWholeAnimationBounds)) {
// Hide the surface when it is outside of the animation area.
t.setAlpha(mLeash, 0);
- } else if (mAnimation.getExtensionEdges() != 0) {
+ } else if (mAnimation.hasExtension()) {
// Allow the surface to be shown in its original bounds in case we want to use edge
// extensions.
cropRect.union(mContentBounds);
@@ -185,7 +180,6 @@
@CallSuper
void onAnimationEnd(@NonNull SurfaceControl.Transaction t) {
onAnimationUpdate(t, mAnimation.getDuration());
- t.setEdgeExtensionEffect(mLeash, /* edge */ 0);
}
final long getDurationHint() {
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 d2cef4b..5696a54 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
@@ -144,10 +144,8 @@
// ending states.
prepareForJumpCut(info, startTransaction);
} else {
- if (!com.android.graphics.libgui.flags.Flags.edgeExtensionShader()) {
- addEdgeExtensionIfNeeded(startTransaction, finishTransaction,
- postStartTransactionCallbacks, adapters);
- }
+ addEdgeExtensionIfNeeded(startTransaction, finishTransaction,
+ postStartTransactionCallbacks, adapters);
addBackgroundColorIfNeeded(info, startTransaction, finishTransaction, adapters);
for (ActivityEmbeddingAnimationAdapter adapter : adapters) {
duration = Math.max(duration, adapter.getDurationHint());
@@ -343,7 +341,7 @@
@NonNull List<ActivityEmbeddingAnimationAdapter> adapters) {
for (ActivityEmbeddingAnimationAdapter adapter : adapters) {
final Animation animation = adapter.mAnimation;
- if (animation.getExtensionEdges() == 0) {
+ if (!animation.hasExtension()) {
continue;
}
if (adapter.mChange.hasFlags(FLAG_TRANSLUCENT)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index a9fdea3..f14f419 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -16,7 +16,12 @@
package com.android.wm.shell.back;
+import static android.view.RemoteAnimationTarget.MODE_CLOSING;
+import static android.view.RemoteAnimationTarget.MODE_OPENING;
+import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED;
+
import static com.android.internal.jank.InteractionJankMonitor.CUJ_PREDICTIVE_BACK_HOME;
+import static com.android.window.flags.Flags.migratePredictiveBackTransition;
import static com.android.window.flags.Flags.predictiveBackSystemAnims;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BACK_ANIMATION;
@@ -30,11 +35,13 @@
import android.content.Context;
import android.content.res.Configuration;
import android.database.ContentObserver;
+import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.input.InputManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
+import android.os.IBinder;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -48,6 +55,7 @@
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl;
import android.view.WindowManager;
import android.window.BackAnimationAdapter;
import android.window.BackEvent;
@@ -57,6 +65,9 @@
import android.window.IBackAnimationFinishedCallback;
import android.window.IBackAnimationRunner;
import android.window.IOnBackInvokedCallback;
+import android.window.TransitionInfo;
+import android.window.TransitionRequestInfo;
+import android.window.WindowContainerTransaction;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.ProtoLog;
@@ -66,12 +77,14 @@
import com.android.wm.shell.common.ExternalInterfaceBinder;
import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.shared.TransitionUtil;
import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
import com.android.wm.shell.shared.annotations.ShellMainThread;
import com.android.wm.shell.sysui.ConfigurationChangeListener;
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.Transitions;
import java.io.PrintWriter;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -101,6 +114,7 @@
/** Tracks if an uninterruptible animation is in progress */
private boolean mPostCommitAnimationInProgress = false;
+ private boolean mRealCallbackInvoked = false;
/** Tracks if we should start the back gesture on the next motion move event */
private boolean mShouldStartOnNextMoveEvent = false;
@@ -123,6 +137,8 @@
private final ShellExecutor mShellExecutor;
private final Handler mBgHandler;
private final WindowManager mWindowManager;
+ private final Transitions mTransitions;
+ private final BackTransitionHandler mBackTransitionHandler;
@VisibleForTesting
final Rect mTouchableArea = new Rect();
@@ -190,7 +206,8 @@
Context context,
@NonNull BackAnimationBackground backAnimationBackground,
ShellBackAnimationRegistry shellBackAnimationRegistry,
- ShellCommandHandler shellCommandHandler) {
+ ShellCommandHandler shellCommandHandler,
+ Transitions transitions) {
this(
shellInit,
shellController,
@@ -201,7 +218,8 @@
context.getContentResolver(),
backAnimationBackground,
shellBackAnimationRegistry,
- shellCommandHandler);
+ shellCommandHandler,
+ transitions);
}
@VisibleForTesting
@@ -215,7 +233,8 @@
ContentResolver contentResolver,
@NonNull BackAnimationBackground backAnimationBackground,
ShellBackAnimationRegistry shellBackAnimationRegistry,
- ShellCommandHandler shellCommandHandler) {
+ ShellCommandHandler shellCommandHandler,
+ Transitions transitions) {
mShellController = shellController;
mShellExecutor = shellExecutor;
mActivityTaskManager = activityTaskManager;
@@ -230,6 +249,9 @@
mLatencyTracker = LatencyTracker.getInstance(mContext);
mShellCommandHandler = shellCommandHandler;
mWindowManager = context.getSystemService(WindowManager.class);
+ mTransitions = transitions;
+ mBackTransitionHandler = new BackTransitionHandler();
+ mTransitions.addHandler(mBackTransitionHandler);
updateTouchableArea();
}
@@ -730,7 +752,7 @@
mBackAnimationFinishedCallback = null;
}
- if (mBackNavigationInfo != null) {
+ if (mBackNavigationInfo != null && !mRealCallbackInvoked) {
final IOnBackInvokedCallback callback = mBackNavigationInfo.getOnBackInvokedCallback();
if (touchTracker.getTriggerBack()) {
dispatchOnBackInvoked(callback);
@@ -738,6 +760,7 @@
tryDispatchOnBackCancelled(callback);
}
}
+ mRealCallbackInvoked = false;
finishBackNavigation(touchTracker.getTriggerBack());
}
@@ -815,14 +838,38 @@
// The next callback should be {@link #onBackAnimationFinished}.
if (mCurrentTracker.getTriggerBack()) {
- // notify gesture finished
- mBackNavigationInfo.onBackGestureFinished(true);
+ if (migratePredictiveBackTransition()) {
+ // notify core gesture is commit
+ if (shouldTriggerCloseTransition()) {
+ mBackTransitionHandler.mCloseTransitionRequested = true;
+ final IOnBackInvokedCallback callback =
+ mBackNavigationInfo.getOnBackInvokedCallback();
+ // invoked client side onBackInvoked
+ dispatchOnBackInvoked(callback);
+ mRealCallbackInvoked = true;
+ }
+ } else {
+ // notify gesture finished
+ mBackNavigationInfo.onBackGestureFinished(true);
+ }
+
+ // start post animation
dispatchOnBackInvoked(mActiveCallback);
} else {
tryDispatchOnBackCancelled(mActiveCallback);
}
}
+ // Close window won't create any transition
+ private boolean shouldTriggerCloseTransition() {
+ if (mBackNavigationInfo == null) {
+ return false;
+ }
+ int type = mBackNavigationInfo.getType();
+ return type == BackNavigationInfo.TYPE_RETURN_TO_HOME
+ || type == BackNavigationInfo.TYPE_CROSS_TASK
+ || type == BackNavigationInfo.TYPE_CROSS_ACTIVITY;
+ }
/**
* Called when the post commit animation is completed or timeout.
* This will trigger the real {@link IOnBackInvokedCallback} behavior.
@@ -857,6 +904,7 @@
"mCurrentBackGestureInfo was null when back animation finished");
}
resetTouchTracker();
+ mBackTransitionHandler.onAnimationFinished();
}
/**
@@ -1016,11 +1064,13 @@
endLatencyTracking();
if (!validateAnimationTargets(apps)) {
Log.e(TAG, "Invalid animation targets!");
+ mBackTransitionHandler.consumeQueuedTransitionIfNeeded();
return;
}
mBackAnimationFinishedCallback = finishedCallback;
mApps = apps;
startSystemAnimation();
+ mBackTransitionHandler.consumeQueuedTransitionIfNeeded();
// Dispatch the first progress after animation start for
// smoothing the initial animation, instead of waiting for next
@@ -1041,6 +1091,7 @@
public void onAnimationCancelled() {
mShellExecutor.execute(
() -> {
+ mBackTransitionHandler.consumeQueuedTransitionIfNeeded();
if (!mShellBackAnimationRegistry.cancel(
mBackNavigationInfo != null
? mBackNavigationInfo.getType()
@@ -1073,4 +1124,249 @@
mQueuedTracker.dump(pw, prefix + " ");
}
+ class BackTransitionHandler implements Transitions.TransitionHandler {
+
+ Runnable mOnAnimationFinishCallback;
+ boolean mCloseTransitionRequested;
+ boolean mOpeningRunning;
+ SurfaceControl.Transaction mFinishOpenTransaction;
+ Transitions.TransitionFinishCallback mFinishOpenTransitionCallback;
+ QueuedTransition mQueuedTransition = null;
+ void onAnimationFinished() {
+ if (!mCloseTransitionRequested) {
+ applyFinishOpenTransition();
+ }
+ if (mOnAnimationFinishCallback != null) {
+ mOnAnimationFinishCallback.run();
+ mOnAnimationFinishCallback = null;
+ }
+ }
+
+ void consumeQueuedTransitionIfNeeded() {
+ if (mQueuedTransition != null) {
+ mQueuedTransition.consume();
+ mQueuedTransition = null;
+ }
+ }
+
+ private void applyFinishOpenTransition() {
+ if (mFinishOpenTransaction != null) {
+ mFinishOpenTransaction.apply();
+ mFinishOpenTransaction = null;
+ }
+ if (mFinishOpenTransitionCallback != null) {
+ mFinishOpenTransitionCallback.onTransitionFinished(null);
+ mFinishOpenTransitionCallback = null;
+ }
+ mOpeningRunning = false;
+ }
+
+ private void applyAndFinish(@NonNull SurfaceControl.Transaction st,
+ @NonNull SurfaceControl.Transaction ft,
+ @NonNull Transitions.TransitionFinishCallback finishCallback) {
+ applyFinishOpenTransition();
+ st.apply();
+ ft.apply();
+ finishCallback.onTransitionFinished(null);
+ mCloseTransitionRequested = false;
+ }
+ @Override
+ public boolean startAnimation(@NonNull IBinder transition,
+ @NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction st,
+ @NonNull SurfaceControl.Transaction ft,
+ @NonNull Transitions.TransitionFinishCallback finishCallback) {
+ // Both mShellExecutor and Transitions#mMainExecutor are ShellMainThread, so we don't
+ // need to post to ShellExecutor when called.
+ if (info.getType() != WindowManager.TRANSIT_PREPARE_BACK_NAVIGATION
+ && !isGestureBackTransition(info)) {
+ return false;
+ }
+ if (mApps == null || mApps.length == 0) {
+ if (mBackNavigationInfo != null && mShellBackAnimationRegistry
+ .isWaitingAnimation(mBackNavigationInfo.getType())) {
+ // Waiting for animation? Queue update to wait for animation start.
+ consumeQueuedTransitionIfNeeded();
+ mQueuedTransition = new QueuedTransition(info, st, ft, finishCallback);
+ } else {
+ // animation was done, consume directly
+ applyAndFinish(st, ft, finishCallback);
+ }
+ return true;
+ }
+
+ if (handlePrepareTransition(info, st, ft, finishCallback)) {
+ return true;
+ }
+ return handleCloseTransition(info, st, ft, finishCallback);
+ }
+
+ @Override
+ public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget,
+ @NonNull Transitions.TransitionFinishCallback finishCallback) {
+ if (!isGestureBackTransition(info)) {
+ if (mOpeningRunning) {
+ applyFinishOpenTransition();
+ }
+ if (mQueuedTransition != null) {
+ consumeQueuedTransitionIfNeeded();
+ }
+ return;
+ }
+ // Handle the commit transition if this handler is running the open transition.
+ finishCallback.onTransitionFinished(null);
+ if (mCloseTransitionRequested) {
+ if (mApps == null || mApps.length == 0) {
+ if (mQueuedTransition == null) {
+ // animation was done
+ applyFinishOpenTransition();
+ mCloseTransitionRequested = false;
+ } // else, let queued transition to play
+ } else {
+ // we are animating, wait until animation finish
+ mOnAnimationFinishCallback = () -> {
+ applyFinishOpenTransition();
+ mCloseTransitionRequested = false;
+ };
+ }
+ }
+ }
+
+ /**
+ * Check whether this transition is prepare for predictive back animation, which could
+ * happen when core make an activity become visible.
+ */
+ private boolean handlePrepareTransition(
+ @NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction st,
+ @NonNull SurfaceControl.Transaction ft,
+ @NonNull Transitions.TransitionFinishCallback finishCallback) {
+ if (info.getType() != WindowManager.TRANSIT_PREPARE_BACK_NAVIGATION) {
+ return false;
+ }
+
+ SurfaceControl openingLeash = null;
+ for (int i = mApps.length - 1; i >= 0; --i) {
+ if (mApps[i].mode == MODE_OPENING) {
+ openingLeash = mApps[i].leash;
+ }
+ }
+ if (openingLeash != null) {
+ for (int i = info.getChanges().size() - 1; i >= 0; --i) {
+ final TransitionInfo.Change c = info.getChanges().get(i);
+ if (TransitionUtil.isOpeningMode(c.getMode())) {
+ final Point offset = c.getEndRelOffset();
+ st.setPosition(c.getLeash(), offset.x, offset.y);
+ st.reparent(c.getLeash(), openingLeash);
+ }
+ }
+ }
+ st.apply();
+ mFinishOpenTransaction = ft;
+ mFinishOpenTransitionCallback = finishCallback;
+ mOpeningRunning = true;
+ return true;
+ }
+
+ private boolean isGestureBackTransition(@NonNull TransitionInfo info) {
+ for (int i = info.getChanges().size() - 1; i >= 0; --i) {
+ final TransitionInfo.Change c = info.getChanges().get(i);
+ if (c.hasFlags(FLAG_BACK_GESTURE_ANIMATED)
+ && (TransitionUtil.isOpeningMode(c.getMode())
+ || TransitionUtil.isClosingMode(c.getMode()))) {
+ return true;
+ }
+ }
+ return false;
+ }
+ /**
+ * Check whether this transition is triggered from back gesture commitment.
+ * Reparent the transition targets to animation leashes, so the animation won't be broken.
+ */
+ private boolean handleCloseTransition(@NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction st,
+ @NonNull SurfaceControl.Transaction ft,
+ @NonNull Transitions.TransitionFinishCallback finishCallback) {
+ SurfaceControl openingLeash = null;
+ SurfaceControl closingLeash = null;
+ for (int i = mApps.length - 1; i >= 0; --i) {
+ if (mApps[i].mode == MODE_OPENING) {
+ openingLeash = mApps[i].leash;
+ }
+ if (mApps[i].mode == MODE_CLOSING) {
+ closingLeash = mApps[i].leash;
+ }
+ }
+ if (openingLeash != null && closingLeash != null) {
+ for (int i = info.getChanges().size() - 1; i >= 0; --i) {
+ final TransitionInfo.Change c = info.getChanges().get(i);
+ if (TransitionUtil.isOpeningMode(c.getMode())) {
+ final Point offset = c.getEndRelOffset();
+ st.setPosition(c.getLeash(), offset.x, offset.y);
+ st.reparent(c.getLeash(), openingLeash);
+ } else if (TransitionUtil.isClosingMode(c.getMode())) {
+ st.reparent(c.getLeash(), closingLeash);
+ }
+ }
+ }
+ st.apply();
+ // mApps must exists
+ mOnAnimationFinishCallback = () -> {
+ ft.apply();
+ finishCallback.onTransitionFinished(null);
+ mCloseTransitionRequested = false;
+ };
+ return true;
+ }
+
+ @Nullable
+ @Override
+ public WindowContainerTransaction handleRequest(
+ @NonNull IBinder transition,
+ @NonNull TransitionRequestInfo request) {
+ if (request.getType() == WindowManager.TRANSIT_PREPARE_BACK_NAVIGATION) {
+ return new WindowContainerTransaction();
+ }
+ if (TransitionUtil.isClosingType(request.getType()) && mCloseTransitionRequested) {
+ return new WindowContainerTransaction();
+ }
+ return null;
+ }
+
+ class QueuedTransition {
+ final TransitionInfo mInfo;
+ final SurfaceControl.Transaction mSt;
+ final SurfaceControl.Transaction mFt;
+ final Transitions.TransitionFinishCallback mFinishCallback;
+ QueuedTransition(@NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction st,
+ @NonNull SurfaceControl.Transaction ft,
+ @NonNull Transitions.TransitionFinishCallback finishCallback) {
+ mInfo = info;
+ mSt = st;
+ mFt = ft;
+ mFinishCallback = finishCallback;
+ }
+
+ void consume() {
+ // not animating, consume transition directly
+ if (mApps == null || mApps.length == 0) {
+ applyAndFinish(mSt, mFt, mFinishCallback);
+ return;
+ }
+ // we are animating
+ if (handlePrepareTransition(mInfo, mSt, mFt, mFinishCallback)) {
+ // handle merge transition if any
+ if (mCloseTransitionRequested) {
+ mOnAnimationFinishCallback = () -> {
+ applyFinishOpenTransition();
+ mCloseTransitionRequested = false;
+ };
+ }
+ }
+ handleCloseTransition(mInfo, mSt, mFt, mFinishCallback);
+ }
+ }
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuView.java
index 211fe0d..d5f4924 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuView.java
@@ -17,6 +17,7 @@
import android.annotation.ColorInt;
import android.content.Context;
+import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Icon;
import android.util.AttributeSet;
@@ -64,6 +65,14 @@
mActionsSectionView = findViewById(R.id.bubble_bar_manage_menu_actions_section);
mBubbleIconView = findViewById(R.id.bubble_bar_manage_menu_bubble_icon);
mBubbleTitleView = findViewById(R.id.bubble_bar_manage_menu_bubble_title);
+ updateActionsBackgroundColor();
+ }
+
+ private void updateActionsBackgroundColor() {
+ try (TypedArray ta = mContext.obtainStyledAttributes(new int[]{
+ com.android.internal.R.attr.materialColorSurfaceBright})) {
+ mActionsSectionView.getBackground().setTint(ta.getColor(0, Color.WHITE));
+ }
}
/** Update menu details with bubble info */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/MultiInstanceHelper.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/common/MultiInstanceHelper.kt
index a6be640..4cd2fd0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/MultiInstanceHelper.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/MultiInstanceHelper.kt
@@ -22,7 +22,6 @@
import android.content.pm.PackageManager
import android.os.UserHandle
import android.view.WindowManager.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI
-import com.android.internal.annotations.VisibleForTesting
import com.android.internal.protolog.ProtoLog
import com.android.wm.shell.R
import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL
@@ -41,7 +40,6 @@
/**
* Returns whether a specific component desires to be launched in multiple instances.
*/
- @VisibleForTesting
fun supportsMultiInstanceSplit(componentName: ComponentName?): Boolean {
if (componentName == null || componentName.packageName == null) {
// TODO(b/262864589): Handle empty component case
@@ -60,7 +58,7 @@
if (!supportsMultiInstanceProperty) {
// If not checking the multi-instance properties, then return early
- return false;
+ return false
}
// Check the activity property first
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerSnapAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerSnapAlgorithm.java
index bc6ed1f..2e1789a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerSnapAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerSnapAlgorithm.java
@@ -16,7 +16,6 @@
package com.android.wm.shell.common.split;
-import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_LEFT;
import static android.view.WindowManager.DOCKED_RIGHT;
@@ -29,13 +28,8 @@
import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_START_AND_DISMISS;
import static com.android.wm.shell.common.split.SplitScreenConstants.SnapPosition;
-import android.content.Context;
-import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
-import android.hardware.display.DisplayManager;
-import android.view.Display;
-import android.view.DisplayInfo;
import androidx.annotation.Nullable;
@@ -86,7 +80,7 @@
private final float mFixedRatio;
/** Allows split ratios to calculated dynamically instead of using {@link #mFixedRatio}. */
private final boolean mAllowFlexibleSplitRatios;
- private boolean mIsHorizontalDivision;
+ private final boolean mIsHorizontalDivision;
/** The first target which is still splitting the screen */
private final SnapTarget mFirstSplitTarget;
@@ -98,27 +92,6 @@
private final SnapTarget mDismissEndTarget;
private final SnapTarget mMiddleTarget;
- public static DividerSnapAlgorithm create(Context ctx, Rect insets) {
- DisplayInfo displayInfo = new DisplayInfo();
- ctx.getSystemService(DisplayManager.class).getDisplay(
- Display.DEFAULT_DISPLAY).getDisplayInfo(displayInfo);
- int dividerWindowWidth = ctx.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.docked_stack_divider_thickness);
- int dividerInsets = ctx.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.docked_stack_divider_insets);
- return new DividerSnapAlgorithm(ctx.getResources(),
- displayInfo.logicalWidth, displayInfo.logicalHeight,
- dividerWindowWidth - 2 * dividerInsets,
- ctx.getApplicationContext().getResources().getConfiguration().orientation
- == Configuration.ORIENTATION_PORTRAIT,
- insets);
- }
-
- public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize,
- boolean isHorizontalDivision, Rect insets) {
- this(res, displayWidth, displayHeight, dividerSize, isHorizontalDivision, insets,
- DOCKED_INVALID, false /* minimized */, true /* resizable */);
- }
public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize,
boolean isHorizontalDivision, Rect insets, int dockSide) {
@@ -160,29 +133,11 @@
}
/**
- * @return whether it's feasible to enable split screen in the current configuration, i.e. when
- * snapping in the middle both tasks are larger than the minimal task size.
- */
- public boolean isSplitScreenFeasible() {
- int statusBarSize = mInsets.top;
- int navBarSize = mIsHorizontalDivision ? mInsets.bottom : mInsets.right;
- int size = mIsHorizontalDivision
- ? mDisplayHeight
- : mDisplayWidth;
- int availableSpace = size - navBarSize - statusBarSize - mDividerSize;
- return availableSpace / 2 >= mMinimalSizeResizableTask;
- }
-
- public SnapTarget calculateSnapTarget(int position, float velocity) {
- return calculateSnapTarget(position, velocity, true /* hardDismiss */);
- }
-
- /**
* @param position the top/left position of the divider
* @param velocity current dragging velocity
- * @param hardDismiss if set, make it a bit harder to get reach the dismiss targets
+ * @param hardToDismiss if set, make it a bit harder to get reach the dismiss targets
*/
- public SnapTarget calculateSnapTarget(int position, float velocity, boolean hardDismiss) {
+ public SnapTarget calculateSnapTarget(int position, float velocity, boolean hardToDismiss) {
if (position < mFirstSplitTarget.position && velocity < -mMinDismissVelocityPxPerSecond) {
return mDismissStartTarget;
}
@@ -190,7 +145,7 @@
return mDismissEndTarget;
}
if (Math.abs(velocity) < mMinFlingVelocityPxPerSecond) {
- return snap(position, hardDismiss);
+ return snap(position, hardToDismiss);
}
if (velocity < 0) {
return mFirstSplitTarget;
@@ -236,19 +191,6 @@
return 0f;
}
- public SnapTarget getClosestDismissTarget(int position) {
- if (position < mFirstSplitTarget.position) {
- return mDismissStartTarget;
- } else if (position > mLastSplitTarget.position) {
- return mDismissEndTarget;
- } else if (position - mDismissStartTarget.position
- < mDismissEndTarget.position - position) {
- return mDismissStartTarget;
- } else {
- return mDismissEndTarget;
- }
- }
-
public SnapTarget getFirstSplitTarget() {
return mFirstSplitTarget;
}
@@ -411,22 +353,6 @@
return mMiddleTarget;
}
- public SnapTarget getNextTarget(SnapTarget snapTarget) {
- int index = mTargets.indexOf(snapTarget);
- if (index != -1 && index < mTargets.size() - 1) {
- return mTargets.get(index + 1);
- }
- return snapTarget;
- }
-
- public SnapTarget getPreviousTarget(SnapTarget snapTarget) {
- int index = mTargets.indexOf(snapTarget);
- if (index != -1 && index > 0) {
- return mTargets.get(index - 1);
- }
- return snapTarget;
- }
-
/**
* @return whether or not there are more than 1 split targets that do not include the two
* dismiss targets, used in deciding to display the middle target for accessibility
@@ -451,26 +377,6 @@
}
/**
- * Cycles through all non-dismiss targets with a stepping of {@param increment}. It moves left
- * if {@param increment} is negative and moves right otherwise.
- */
- public SnapTarget cycleNonDismissTarget(SnapTarget snapTarget, int increment) {
- int index = mTargets.indexOf(snapTarget);
- if (index != -1) {
- SnapTarget newTarget = mTargets.get((index + mTargets.size() + increment)
- % mTargets.size());
- if (newTarget == mDismissStartTarget) {
- return mLastSplitTarget;
- } else if (newTarget == mDismissEndTarget) {
- return mFirstSplitTarget;
- } else {
- return newTarget;
- }
- }
- return snapTarget;
- }
-
- /**
* Represents a snap target for the divider.
*/
public static class SnapTarget {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUILayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUILayout.java
index 2b0bd32..688f8ca 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUILayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUILayout.java
@@ -16,10 +16,7 @@
package com.android.wm.shell.compatui;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
-
import android.annotation.IdRes;
-import android.app.CameraCompatTaskInfo.CameraCompatControlState;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
@@ -57,28 +54,10 @@
mWindowManager = windowManager;
}
- void updateCameraTreatmentButton(@CameraCompatControlState int newState) {
- int buttonBkgId = newState == CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED
- ? R.drawable.camera_compat_treatment_suggested_ripple
- : R.drawable.camera_compat_treatment_applied_ripple;
- int hintStringId = newState == CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED
- ? R.string.camera_compat_treatment_suggested_button_description
- : R.string.camera_compat_treatment_applied_button_description;
- final ImageButton button = findViewById(R.id.camera_compat_treatment_button);
- button.setImageResource(buttonBkgId);
- button.setContentDescription(getResources().getString(hintStringId));
- final LinearLayout hint = findViewById(R.id.camera_compat_hint);
- ((TextView) hint.findViewById(R.id.compat_mode_hint_text)).setText(hintStringId);
- }
-
void setSizeCompatHintVisibility(boolean show) {
setViewVisibility(R.id.size_compat_hint, show);
}
- void setCameraCompatHintVisibility(boolean show) {
- setViewVisibility(R.id.camera_compat_hint, show);
- }
-
void setRestartButtonVisibility(boolean show) {
setViewVisibility(R.id.size_compat_restart_button, show);
// Hint should never be visible without button.
@@ -87,14 +66,6 @@
}
}
- void setCameraControlVisibility(boolean show) {
- setViewVisibility(R.id.camera_compat_control, show);
- // Hint should never be visible without button.
- if (!show) {
- setCameraCompatHintVisibility(/* show= */ false);
- }
- }
-
private void setViewVisibility(@IdRes int resId, boolean show) {
final View view = findViewById(resId);
int visibility = show ? View.VISIBLE : View.GONE;
@@ -127,26 +98,5 @@
((TextView) sizeCompatHint.findViewById(R.id.compat_mode_hint_text))
.setText(R.string.restart_button_description);
sizeCompatHint.setOnClickListener(view -> setSizeCompatHintVisibility(/* show= */ false));
-
- final ImageButton cameraTreatmentButton =
- findViewById(R.id.camera_compat_treatment_button);
- cameraTreatmentButton.setOnClickListener(
- view -> mWindowManager.onCameraTreatmentButtonClicked());
- cameraTreatmentButton.setOnLongClickListener(view -> {
- mWindowManager.onCameraButtonLongClicked();
- return true;
- });
-
- final ImageButton cameraDismissButton = findViewById(R.id.camera_compat_dismiss_button);
- cameraDismissButton.setOnClickListener(
- view -> mWindowManager.onCameraDismissButtonClicked());
- cameraDismissButton.setOnLongClickListener(view -> {
- mWindowManager.onCameraButtonLongClicked();
- return true;
- });
-
- final LinearLayout cameraCompatHint = findViewById(R.id.camera_compat_hint);
- cameraCompatHint.setOnClickListener(
- view -> setCameraCompatHintVisibility(/* show= */ false));
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java
index d289ef2..271c07d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java
@@ -16,10 +16,6 @@
package com.android.wm.shell.compatui;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
import static android.view.WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI;
@@ -27,11 +23,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.CameraCompatTaskInfo.CameraCompatControlState;
import android.app.TaskInfo;
import android.content.Context;
import android.graphics.Rect;
-import android.util.Log;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
@@ -44,7 +38,6 @@
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.compatui.CompatUIController.CompatUIHintsState;
import com.android.wm.shell.compatui.api.CompatUIEvent;
-import com.android.wm.shell.compatui.impl.CompatUIEvents.CameraControlStateUpdated;
import com.android.wm.shell.compatui.impl.CompatUIEvents.SizeCompatRestartButtonAppeared;
import com.android.wm.shell.shared.desktopmode.DesktopModeFlags;
@@ -69,10 +62,6 @@
boolean mHasSizeCompat;
@VisibleForTesting
- @CameraCompatControlState
- int mCameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN;
-
- @VisibleForTesting
@NonNull
CompatUIHintsState mCompatUIHintsState;
@@ -99,8 +88,6 @@
// Don't show the SCM button for freeform tasks
mHasSizeCompat &= !taskInfo.isFreeform();
}
- mCameraCompatControlState =
- taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState;
mCompatUIHintsState = compatUIHintsState;
mCompatUIConfiguration = compatUIConfiguration;
mOnRestartButtonClicked = onRestartButtonClicked;
@@ -124,8 +111,7 @@
@Override
protected boolean eligibleToShowLayout() {
- return (mHasSizeCompat && shouldShowSizeCompatRestartButton(getLastTaskInfo()))
- || shouldShowCameraControl();
+ return mHasSizeCompat && shouldShowSizeCompatRestartButton(getLastTaskInfo());
}
@Override
@@ -152,22 +138,18 @@
public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener,
boolean canShow) {
final boolean prevHasSizeCompat = mHasSizeCompat;
- final int prevCameraCompatControlState = mCameraCompatControlState;
mHasSizeCompat = taskInfo.appCompatTaskInfo.topActivityInSizeCompat;
if (DESKTOP_WINDOWING_MODE.isEnabled(mContext)
&& DesktopModeFlags.DYNAMIC_INITIAL_BOUNDS.isEnabled(mContext)) {
// Don't show the SCM button for freeform tasks
mHasSizeCompat &= !taskInfo.isFreeform();
}
- mCameraCompatControlState =
- taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState;
if (!super.updateCompatInfo(taskInfo, taskListener, canShow)) {
return false;
}
- if (prevHasSizeCompat != mHasSizeCompat
- || prevCameraCompatControlState != mCameraCompatControlState) {
+ if (prevHasSizeCompat != mHasSizeCompat) {
updateVisibilityOfViews();
}
@@ -179,34 +161,6 @@
mOnRestartButtonClicked.accept(Pair.create(getLastTaskInfo(), getTaskListener()));
}
- /** Called when the camera treatment button is clicked. */
- void onCameraTreatmentButtonClicked() {
- if (!shouldShowCameraControl()) {
- Log.w(getTag(), "Camera compat shouldn't receive clicks in the hidden state.");
- return;
- }
- // When a camera control is shown, only two states are allowed: "treament applied" and
- // "treatment suggested". Clicks on the conrol's treatment button toggle between these
- // two states.
- mCameraCompatControlState =
- mCameraCompatControlState == CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED
- ? CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED
- : CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
- mCallback.accept(new CameraControlStateUpdated(mTaskId, mCameraCompatControlState));
- mLayout.updateCameraTreatmentButton(mCameraCompatControlState);
- }
-
- /** Called when the camera dismiss button is clicked. */
- void onCameraDismissButtonClicked() {
- if (!shouldShowCameraControl()) {
- Log.w(getTag(), "Camera compat shouldn't receive clicks in the hidden state.");
- return;
- }
- mCameraCompatControlState = CAMERA_COMPAT_CONTROL_DISMISSED;
- mCallback.accept(new CameraControlStateUpdated(mTaskId, CAMERA_COMPAT_CONTROL_DISMISSED));
- mLayout.setCameraControlVisibility(/* show= */ false);
- }
-
/** Called when the restart button is long clicked. */
void onRestartButtonLongClicked() {
if (mLayout == null) {
@@ -215,14 +169,6 @@
mLayout.setSizeCompatHintVisibility(/* show= */ true);
}
- /** Called when either dismiss or treatment camera buttons is long clicked. */
- void onCameraButtonLongClicked() {
- if (mLayout == null) {
- return;
- }
- mLayout.setCameraCompatHintVisibility(/* show= */ true);
- }
-
@Override
@VisibleForTesting
public void updateSurfacePosition() {
@@ -270,6 +216,7 @@
return false;
}
final float percentageAreaOfLetterboxInTask = (float) letterboxArea / taskArea * 100;
+
return percentageAreaOfLetterboxInTask < mHideScmTolerance;
}
@@ -284,21 +231,5 @@
mLayout.setSizeCompatHintVisibility(/* show= */ true);
mCompatUIHintsState.mHasShownSizeCompatHint = true;
}
-
- // Camera control for stretched issues.
- mLayout.setCameraControlVisibility(shouldShowCameraControl());
- // Only show by default for the first time.
- if (shouldShowCameraControl() && !mCompatUIHintsState.mHasShownCameraCompatHint) {
- mLayout.setCameraCompatHintVisibility(/* show= */ true);
- mCompatUIHintsState.mHasShownCameraCompatHint = true;
- }
- if (shouldShowCameraControl()) {
- mLayout.updateCameraTreatmentButton(mCameraCompatControlState);
- }
- }
-
- private boolean shouldShowCameraControl() {
- return mCameraCompatControlState != CAMERA_COMPAT_CONTROL_HIDDEN
- && mCameraCompatControlState != CAMERA_COMPAT_CONTROL_DISMISSED;
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponent.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponent.kt
new file mode 100644
index 0000000..9ee50ac
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponent.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.compatui.api
+
+import android.util.Log
+
+/**
+ * The component created after a {@link CompatUISpec} definition
+ */
+class CompatUIComponent(
+ private val spec: CompatUISpec,
+ private val id: String
+) {
+
+ /**
+ * Invoked every time a new CompatUIInfo comes from core
+ * @param newInfo The new CompatUIInfo object
+ * @param sharedState The state shared between all the component
+ */
+ fun update(newInfo: CompatUIInfo, state: CompatUIState) {
+ // TODO(b/322817374): To be removed when the implementation is provided.
+ Log.d("CompatUIComponent", "update() newInfo: $newInfo state:$state")
+ }
+
+ fun release() {
+ // TODO(b/322817374): To be removed when the implementation is provided.
+ Log.d("CompatUIComponent", "release()")
+ }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponentIdGenerator.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponentIdGenerator.kt
new file mode 100644
index 0000000..7d663fa
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponentIdGenerator.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.compatui.api
+
+/**
+ * Any object responsible to generate an id for a component.
+ */
+interface CompatUIComponentIdGenerator {
+
+ /**
+ * Generates the unique id for a component given a {@link CompatUIInfo} and component
+ * {@link CompatUISpec}.
+ * @param compatUIInfo The object encapsulating information about the current Task.
+ * @param spec The {@link CompatUISpec} for the component.
+ */
+ fun generateId(compatUIInfo: CompatUIInfo, spec: CompatUISpec): String
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponentState.kt
similarity index 68%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
copy to libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponentState.kt
index 1f04a44..dcaea00 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponentState.kt
@@ -14,12 +14,11 @@
* limitations under the License.
*/
-package com.android.systemui.activatable
+package com.android.wm.shell.compatui.api
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.TestScope
-
-/** Activates [activatable] for the duration of the test. */
-fun Activatable.activateIn(testScope: TestScope) {
- testScope.backgroundScope.launch { activate() }
-}
+/**
+ * Abstraction of all the component specific state. Each
+ * component can create its own state implementing this
+ * tagging interface.
+ */
+interface CompatUIComponentState
\ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/education/GestureType.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUISharedState.kt
similarity index 74%
rename from packages/SystemUI/shared/src/com/android/systemui/shared/education/GestureType.kt
rename to libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUISharedState.kt
index 9a5c77a..33e0d46 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/education/GestureType.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUISharedState.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2024 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-package com.android.systemui.shared.education
+package com.android.wm.shell.compatui.api
-enum class GestureType {
- BACK_GESTURE,
-}
+/**
+ * Represents the state shared between all the components.
+ */
+class CompatUISharedState
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUISpec.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUISpec.kt
index 24c2c8c..a520d5e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUISpec.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUISpec.kt
@@ -17,10 +17,31 @@
package com.android.wm.shell.compatui.api
/**
+ * Defines the predicates to invoke for understanding if a component can be created or destroyed.
+ */
+class CompatUILifecyclePredicates(
+ // Predicate evaluating to true if the component needs to be created
+ val creationPredicate: (CompatUIInfo, CompatUISharedState) -> Boolean,
+ // Predicate evaluating to true if the component needs to be destroyed
+ val removalPredicate: (
+ CompatUIInfo,
+ CompatUISharedState,
+ CompatUIComponentState?
+ ) -> Boolean,
+ // Builder for the initial state of the component
+ val stateBuilder: (
+ CompatUIInfo,
+ CompatUISharedState
+ ) -> CompatUIComponentState? = { _, _ -> null }
+)
+
+/**
* Describes each compat ui component to the framework.
*/
-data class CompatUISpec(
+class CompatUISpec(
// Unique name for the component. It's used for debug and for generating the
// unique component identifier in the system.
- val name: String
-)
\ No newline at end of file
+ val name: String,
+ // The lifecycle definition
+ val lifecycle: CompatUILifecyclePredicates
+)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIState.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIState.kt
new file mode 100644
index 0000000..68307b4
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIState.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.compatui.api
+
+/**
+ * Singleton which contains the global state of the compat ui system.
+ */
+class CompatUIState {
+
+ private val components = mutableMapOf<String, CompatUIComponent>()
+
+ val sharedState = CompatUISharedState()
+
+ val componentStates = mutableMapOf<String, CompatUIComponentState>()
+
+ /**
+ * @return The CompatUIComponent for the given componentId if it exists.
+ */
+ fun getUIComponent(componentId: String): CompatUIComponent? =
+ components[componentId]
+
+ /**
+ * Registers a component for a given componentId along with its optional state.
+ * <p/>
+ * @param componentId The identifier for the component to register.
+ * @param comp The {@link CompatUIComponent} instance to register.
+ * @param componentState The optional state specific of the component. Not all components
+ * have a specific state so it can be null.
+ */
+ fun registerUIComponent(
+ componentId: String,
+ comp: CompatUIComponent,
+ componentState: CompatUIComponentState?
+ ) {
+ components[componentId] = comp
+ componentState?.let {
+ componentStates[componentId] = componentState
+ }
+ }
+
+ /**
+ * Unregister a component for a given componentId.
+ * <p/>
+ * @param componentId The identifier for the component to register.
+ */
+ fun unregisterUIComponent(componentId: String) {
+ components.remove(componentId)
+ componentStates.remove(componentId)
+ }
+
+ /**
+ * Get access to the specific {@link CompatUIComponentState} for a {@link CompatUIComponent}
+ * with a given identifier.
+ * <p/>
+ * @param componentId The identifier of the {@link CompatUIComponent}.
+ * @return The optional state for the component of the provided id.
+ */
+ @Suppress("UNCHECKED_CAST")
+ fun <T : CompatUIComponentState> stateForComponent(componentId: String) =
+ componentStates[componentId] as? T
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/CompatUIEvents.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/CompatUIEvents.kt
index 58ce8ed..db3fda0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/CompatUIEvents.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/CompatUIEvents.kt
@@ -16,13 +16,10 @@
package com.android.wm.shell.compatui.impl
-import android.app.AppCompatTaskInfo
-import android.app.CameraCompatTaskInfo
import com.android.wm.shell.compatui.api.CompatUIEvent
internal const val SIZE_COMPAT_RESTART_BUTTON_APPEARED = 0
internal const val SIZE_COMPAT_RESTART_BUTTON_CLICKED = 1
-internal const val CAMERA_CONTROL_STATE_UPDATE = 2
/**
* All the {@link CompatUIEvent} the Compat UI Framework can handle
@@ -30,15 +27,9 @@
sealed class CompatUIEvents(override val eventId: Int) : CompatUIEvent {
/** Sent when the size compat restart button appears. */
data class SizeCompatRestartButtonAppeared(val taskId: Int) :
- CompatUIEvents(SIZE_COMPAT_RESTART_BUTTON_APPEARED)
+ CompatUIEvents(SIZE_COMPAT_RESTART_BUTTON_APPEARED)
/** Sent when the size compat restart button is clicked. */
data class SizeCompatRestartButtonClicked(val taskId: Int) :
- CompatUIEvents(SIZE_COMPAT_RESTART_BUTTON_CLICKED)
-
- /** Sent when the camera compat control state is updated. */
- data class CameraControlStateUpdated(
- val taskId: Int,
- @CameraCompatTaskInfo.CameraCompatControlState val state: Int
- ) : CompatUIEvents(CAMERA_CONTROL_STATE_UPDATE)
-}
\ No newline at end of file
+ CompatUIEvents(SIZE_COMPAT_RESTART_BUTTON_CLICKED)
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/DefaultCompatUIHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/DefaultCompatUIHandler.kt
index 8408ea6..a7d1b42 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/DefaultCompatUIHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/DefaultCompatUIHandler.kt
@@ -16,25 +16,70 @@
package com.android.wm.shell.compatui.impl
+import com.android.wm.shell.compatui.api.CompatUIComponent
+import com.android.wm.shell.compatui.api.CompatUIComponentIdGenerator
import com.android.wm.shell.compatui.api.CompatUIEvent
import com.android.wm.shell.compatui.api.CompatUIHandler
import com.android.wm.shell.compatui.api.CompatUIInfo
import com.android.wm.shell.compatui.api.CompatUIRepository
+import com.android.wm.shell.compatui.api.CompatUIState
import java.util.function.Consumer
+import java.util.function.IntSupplier
/**
* Default implementation of {@link CompatUIHandler} to handle CompatUI components
*/
class DefaultCompatUIHandler(
- private val compatUIRepository: CompatUIRepository
+ private val compatUIRepository: CompatUIRepository,
+ private val compatUIState: CompatUIState,
+ private val componentIdGenerator: CompatUIComponentIdGenerator
) : CompatUIHandler {
private var compatUIEventSender: Consumer<CompatUIEvent>? = null
+
override fun onCompatInfoChanged(compatUIInfo: CompatUIInfo) {
+ compatUIRepository.iterateOn { spec ->
+ // We get the identifier for the component depending on the task and spec
+ val componentId = componentIdGenerator.generateId(compatUIInfo, spec)
+ // We check in the state if the component already exists
+ var comp = compatUIState.getUIComponent(componentId)
+ if (comp == null) {
+ // We evaluate the predicate
+ if (spec.lifecycle.creationPredicate(compatUIInfo, compatUIState.sharedState)) {
+ // We create the component and store in the
+ // global state
+ comp = CompatUIComponent(spec, componentId)
+ // We initialize the state for the component
+ val compState = spec.lifecycle.stateBuilder(
+ compatUIInfo,
+ compatUIState.sharedState
+ )
+ compatUIState.registerUIComponent(componentId, comp, compState)
+ // Now we can invoke the update passing the shared state and
+ // the state specific to the component
+ comp.update(compatUIInfo, compatUIState)
+ }
+ } else {
+ // The component is present. We check if we need to remove it
+ if (spec.lifecycle.removalPredicate(
+ compatUIInfo,
+ compatUIState.sharedState,
+ compatUIState.stateForComponent(componentId)
+ )) {
+ // We clean the component
+ comp.release()
+ // We remove the component
+ compatUIState.unregisterUIComponent(componentId)
+ } else {
+ // The component exists so we need to invoke the update methods
+ comp.update(compatUIInfo, compatUIState)
+ }
+ }
+ }
// Empty at the moment
}
override fun setCallback(compatUIEventSender: Consumer<CompatUIEvent>?) {
this.compatUIEventSender = compatUIEventSender
}
-}
\ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/DefaultComponentIdGenerator.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/DefaultComponentIdGenerator.kt
new file mode 100644
index 0000000..446291b
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/DefaultComponentIdGenerator.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.compatui.impl
+
+import com.android.wm.shell.compatui.api.CompatUIComponentIdGenerator
+import com.android.wm.shell.compatui.api.CompatUIInfo
+import com.android.wm.shell.compatui.api.CompatUISpec
+
+/**
+ * Default {@link CompatUIComponentIdGenerator} implementation.
+ */
+class DefaultComponentIdGenerator : CompatUIComponentIdGenerator {
+ /**
+ * Simple implementation generating the id from taskId and component name.
+ */
+ override fun generateId(compatUIInfo: CompatUIInfo, spec: CompatUISpec): String =
+ "${compatUIInfo.taskInfo.taskId}-${spec.name}"
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 2dc6382..f22dcce 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -18,6 +18,7 @@
import static com.android.wm.shell.onehanded.OneHandedController.SUPPORT_ONE_HANDED_MODE;
+import android.annotation.NonNull;
import android.app.ActivityTaskManager;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -71,10 +72,13 @@
import com.android.wm.shell.compatui.CompatUIConfiguration;
import com.android.wm.shell.compatui.CompatUIController;
import com.android.wm.shell.compatui.CompatUIShellCommandHandler;
+import com.android.wm.shell.compatui.api.CompatUIComponentIdGenerator;
import com.android.wm.shell.compatui.api.CompatUIHandler;
import com.android.wm.shell.compatui.api.CompatUIRepository;
+import com.android.wm.shell.compatui.api.CompatUIState;
import com.android.wm.shell.compatui.impl.DefaultCompatUIHandler;
import com.android.wm.shell.compatui.impl.DefaultCompatUIRepository;
+import com.android.wm.shell.compatui.impl.DefaultComponentIdGenerator;
import com.android.wm.shell.desktopmode.DesktopMode;
import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
import com.android.wm.shell.desktopmode.DesktopTasksController;
@@ -248,12 +252,15 @@
Lazy<CompatUIConfiguration> compatUIConfiguration,
Lazy<CompatUIShellCommandHandler> compatUIShellCommandHandler,
Lazy<AccessibilityManager> accessibilityManager,
- CompatUIRepository compatUIRepository) {
+ CompatUIRepository compatUIRepository,
+ @NonNull CompatUIState compatUIState,
+ @NonNull CompatUIComponentIdGenerator componentIdGenerator) {
if (!context.getResources().getBoolean(R.bool.config_enableCompatUIController)) {
return Optional.empty();
}
if (Flags.appCompatUiFramework()) {
- return Optional.of(new DefaultCompatUIHandler(compatUIRepository));
+ return Optional.of(new DefaultCompatUIHandler(compatUIRepository, compatUIState,
+ componentIdGenerator));
}
return Optional.of(
new CompatUIController(
@@ -274,6 +281,18 @@
@WMSingleton
@Provides
+ static CompatUIState provideCompatUIState() {
+ return new CompatUIState();
+ }
+
+ @WMSingleton
+ @Provides
+ static CompatUIComponentIdGenerator provideCompatUIComponentIdGenerator() {
+ return new DefaultComponentIdGenerator();
+ }
+
+ @WMSingleton
+ @Provides
static CompatUIRepository provideCompatUIRepository() {
return new DefaultCompatUIRepository();
}
@@ -375,7 +394,8 @@
@ShellBackgroundThread Handler backgroundHandler,
BackAnimationBackground backAnimationBackground,
Optional<ShellBackAnimationRegistry> shellBackAnimationRegistry,
- ShellCommandHandler shellCommandHandler) {
+ ShellCommandHandler shellCommandHandler,
+ Transitions transitions) {
if (BackAnimationController.IS_ENABLED) {
return shellBackAnimationRegistry.map(
(animations) ->
@@ -387,7 +407,8 @@
context,
backAnimationBackground,
animations,
- shellCommandHandler));
+ shellCommandHandler,
+ transitions));
}
return Optional.empty();
}
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 0262507..a18bbad 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
@@ -67,6 +67,7 @@
import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler;
import com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler;
import com.android.wm.shell.desktopmode.ExitDesktopTaskTransitionHandler;
+import com.android.wm.shell.desktopmode.ReturnToDragStartAnimator;
import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler;
import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.draganddrop.GlobalDragListener;
@@ -226,7 +227,8 @@
Optional<DesktopTasksController> desktopTasksController,
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
InteractionJankMonitor interactionJankMonitor,
- AppToWebGenericLinksParser genericLinksParser) {
+ AppToWebGenericLinksParser genericLinksParser,
+ MultiInstanceHelper multiInstanceHelper) {
if (DesktopModeStatus.canEnterDesktopMode(context)) {
return new DesktopModeWindowDecorViewModel(
context,
@@ -246,7 +248,8 @@
desktopTasksController,
rootTaskDisplayAreaOrganizer,
interactionJankMonitor,
- genericLinksParser);
+ genericLinksParser,
+ multiInstanceHelper);
}
return new CaptionWindowDecorViewModel(
context,
@@ -536,6 +539,7 @@
DragAndDropController dragAndDropController,
Transitions transitions,
KeyguardManager keyguardManager,
+ ReturnToDragStartAnimator returnToDragStartAnimator,
EnterDesktopTaskTransitionHandler enterDesktopTransitionHandler,
ExitDesktopTaskTransitionHandler exitDesktopTransitionHandler,
ToggleResizeDesktopTaskTransitionHandler toggleResizeDesktopTaskTransitionHandler,
@@ -551,13 +555,13 @@
InteractionJankMonitor interactionJankMonitor) {
return new DesktopTasksController(context, shellInit, shellCommandHandler, shellController,
displayController, shellTaskOrganizer, syncQueue, rootTaskDisplayAreaOrganizer,
- dragAndDropController, transitions, keyguardManager, enterDesktopTransitionHandler,
+ dragAndDropController, transitions, keyguardManager,
+ returnToDragStartAnimator, enterDesktopTransitionHandler,
exitDesktopTransitionHandler, toggleResizeDesktopTaskTransitionHandler,
dragToDesktopTransitionHandler, desktopModeTaskRepository,
desktopModeLoggerTransitionObserver, launchAdjacentController,
- recentsTransitionHandler, multiInstanceHelper,
- mainExecutor, desktopTasksLimiter, recentTasksController.orElse(null),
- interactionJankMonitor);
+ recentsTransitionHandler, multiInstanceHelper, mainExecutor, desktopTasksLimiter,
+ recentTasksController.orElse(null), interactionJankMonitor);
}
@WMSingleton
@@ -566,7 +570,8 @@
Context context,
Transitions transitions,
@DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository,
- ShellTaskOrganizer shellTaskOrganizer) {
+ ShellTaskOrganizer shellTaskOrganizer,
+ InteractionJankMonitor interactionJankMonitor) {
int maxTaskLimit = DesktopModeStatus.getMaxTaskLimit(context);
if (!DesktopModeStatus.canEnterDesktopMode(context)
|| !ENABLE_DESKTOP_WINDOWING_TASK_LIMIT.isEnabled(context)
@@ -575,7 +580,20 @@
}
return Optional.of(
new DesktopTasksLimiter(
- transitions, desktopModeTaskRepository, shellTaskOrganizer, maxTaskLimit));
+ transitions,
+ desktopModeTaskRepository,
+ shellTaskOrganizer,
+ maxTaskLimit,
+ interactionJankMonitor,
+ context)
+ );
+ }
+
+ @WMSingleton
+ @Provides
+ static ReturnToDragStartAnimator provideReturnToDragStartAnimator(
+ InteractionJankMonitor interactionJankMonitor) {
+ return new ReturnToDragStartAnimator(interactionJankMonitor);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeShellCommandHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeShellCommandHandler.kt
index 1a6ca0e..eca3c1f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeShellCommandHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeShellCommandHandler.kt
@@ -63,8 +63,7 @@
pw.println("Error: task id should be an integer")
return false
}
-
- return controller.moveToDesktop(taskId, transitionSource = UNKNOWN)
+ return controller.moveTaskToDesktop(taskId, transitionSource = UNKNOWN)
}
private fun runMoveToNextDisplay(args: Array<String>, pw: PrintWriter): Boolean {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt
index 4bec788..8375294 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt
@@ -213,7 +213,7 @@
* If task was visible on a different display with a different [displayId], removes from
* the set of visible tasks on that display and notifies listeners.
*/
- fun updateVisibleFreeformTasks(displayId: Int, taskId: Int, visible: Boolean) {
+ fun updateTaskVisibility(displayId: Int, taskId: Int, visible: Boolean) {
if (visible) {
// If task is visible, remove it from any other display besides [displayId].
removeVisibleTask(taskId, excludedDisplayId = displayId)
@@ -250,11 +250,17 @@
logD("getVisibleTaskCount=$it")
}
- /** Adds task (or moves if it already exists) to the top of the ordered list. */
+ /**
+ * Adds task (or moves if it already exists) to the top of the ordered list.
+ *
+ * Unminimizes the task if it is minimized.
+ */
fun addOrMoveFreeformTaskToTop(displayId: Int, taskId: Int) {
logD("Add or move task to top: display=%d taskId=%d", taskId, displayId)
desktopTaskDataByDisplayId[displayId]?.freeformTasksInZOrder?.remove(taskId)
desktopTaskDataByDisplayId.getOrCreate(displayId).freeformTasksInZOrder.add(0, taskId)
+ // Unminimize the task if it is minimized.
+ unminimizeTask(displayId, taskId)
}
/** Minimizes the task for [taskId] and [displayId] */
@@ -294,13 +300,17 @@
}
}
- /** Removes given task from a valid [displayId]. */
+ /** Removes given task from a valid [displayId] and updates the repository state. */
private fun removeTaskFromDisplay(displayId: Int, taskId: Int) {
logD("Removes freeform task: taskId=%d, displayId=%d", taskId, displayId)
desktopTaskDataByDisplayId[displayId]?.freeformTasksInZOrder?.remove(taskId)
boundsBeforeMaximizeByTaskId.remove(taskId)
logD("Remaining freeform tasks: %s",
desktopTaskDataByDisplayId[displayId]?.freeformTasksInZOrder?.toDumpString())
+ // Remove task from unminimized task if it is minimized.
+ unminimizeTask(displayId, taskId)
+ removeActiveTask(taskId)
+ updateTaskVisibility(displayId, taskId, visible = false);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt
index 9fcf73d..026094c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt
@@ -63,7 +63,8 @@
if (taskInfo.isResizeable) {
if (isFixedOrientationPortrait(topActivityInfo.screenOrientation)) {
// Respect apps fullscreen width
- Size(taskInfo.appCompatTaskInfo.topActivityLetterboxWidth, idealSize.height)
+ Size(taskInfo.appCompatTaskInfo.topActivityLetterboxAppWidth,
+ idealSize.height)
} else {
idealSize
}
@@ -79,7 +80,7 @@
// Respect apps fullscreen height and apply custom app width
Size(
customPortraitWidthForLandscapeApp,
- taskInfo.appCompatTaskInfo.topActivityLetterboxHeight
+ taskInfo.appCompatTaskInfo.topActivityLetterboxAppHeight
)
} else {
idealSize
@@ -143,9 +144,9 @@
/** Calculates the aspect ratio of an activity from its fullscreen bounds. */
fun calculateAspectRatio(taskInfo: RunningTaskInfo): Float {
+ val appLetterboxWidth = taskInfo.appCompatTaskInfo.topActivityLetterboxAppWidth
+ val appLetterboxHeight = taskInfo.appCompatTaskInfo.topActivityLetterboxAppHeight
if (taskInfo.appCompatTaskInfo.topActivityBoundsLetterboxed) {
- val appLetterboxWidth = taskInfo.appCompatTaskInfo.topActivityLetterboxWidth
- val appLetterboxHeight = taskInfo.appCompatTaskInfo.topActivityLetterboxHeight
return maxOf(appLetterboxWidth, appLetterboxHeight) /
minOf(appLetterboxWidth, appLetterboxHeight).toFloat()
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index 5f838d3..e154da5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -54,7 +54,6 @@
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.policy.ScreenDecorationsUtils
import com.android.internal.protolog.ProtoLog
-import com.android.window.flags.Flags
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.common.DisplayController
@@ -67,7 +66,6 @@
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.common.SingleInstanceRemoteListener
import com.android.wm.shell.common.SyncTransactionQueue
-import com.android.wm.shell.shared.desktopmode.DesktopModeFlags.WALLPAPER_ACTIVITY
import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource
import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT
import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT
@@ -80,13 +78,14 @@
import com.android.wm.shell.recents.RecentTasksController
import com.android.wm.shell.recents.RecentsTransitionHandler
import com.android.wm.shell.recents.RecentsTransitionStateListener
-import com.android.wm.shell.shared.desktopmode.DesktopModeFlags
-import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
-import com.android.wm.shell.shared.desktopmode.DesktopModeStatus.DESKTOP_DENSITY_OVERRIDE
-import com.android.wm.shell.shared.desktopmode.DesktopModeStatus.useDesktopOverrideDensity
import com.android.wm.shell.shared.TransitionUtil
import com.android.wm.shell.shared.annotations.ExternalThread
import com.android.wm.shell.shared.annotations.ShellMainThread
+import com.android.wm.shell.shared.desktopmode.DesktopModeFlags
+import com.android.wm.shell.shared.desktopmode.DesktopModeFlags.WALLPAPER_ACTIVITY
+import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
+import com.android.wm.shell.shared.desktopmode.DesktopModeStatus.DESKTOP_DENSITY_OVERRIDE
+import com.android.wm.shell.shared.desktopmode.DesktopModeStatus.useDesktopOverrideDensity
import com.android.wm.shell.splitscreen.SplitScreenController
import com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DESKTOP_MODE
import com.android.wm.shell.sysui.ShellCommandHandler
@@ -97,8 +96,10 @@
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.windowdecor.DragPositioningCallbackUtility
import com.android.wm.shell.windowdecor.MoveToDesktopAnimator
+import com.android.wm.shell.windowdecor.OnTaskRepositionAnimationListener
import com.android.wm.shell.windowdecor.OnTaskResizeAnimationListener
import com.android.wm.shell.windowdecor.extension.isFullscreen
+import com.android.wm.shell.windowdecor.extension.isMultiWindow
import java.io.PrintWriter
import java.util.Optional
import java.util.concurrent.Executor
@@ -117,6 +118,7 @@
private val dragAndDropController: DragAndDropController,
private val transitions: Transitions,
private val keyguardManager: KeyguardManager,
+ private val returnToDragStartAnimator: ReturnToDragStartAnimator,
private val enterDesktopTaskTransitionHandler: EnterDesktopTaskTransitionHandler,
private val exitDesktopTaskTransitionHandler: ExitDesktopTaskTransitionHandler,
private val toggleResizeDesktopTaskTransitionHandler: ToggleResizeDesktopTaskTransitionHandler,
@@ -214,6 +216,10 @@
dragToDesktopTransitionHandler.setOnTaskResizeAnimatorListener(listener)
}
+ fun setOnTaskRepositionAnimationListener(listener: OnTaskRepositionAnimationListener) {
+ returnToDragStartAnimator.setTaskRepositionAnimationListener(listener)
+ }
+
/** Setter needed to avoid cyclic dependency. */
fun setSplitScreenController(controller: SplitScreenController) {
splitScreenController = controller
@@ -256,81 +262,82 @@
/** Returns true if any tasks are visible in Desktop Mode. */
fun isDesktopModeShowing(displayId: Int): Boolean = visibleTaskCount(displayId) > 0
- /** Enter desktop by using the focused task in given `displayId` */
+ /** Moves focused task to desktop mode for given [displayId]. */
fun moveFocusedTaskToDesktop(displayId: Int, transitionSource: DesktopModeTransitionSource) {
- val allFocusedTasks =
- shellTaskOrganizer.getRunningTasks(displayId).filter { taskInfo ->
- taskInfo.isFocused &&
- (taskInfo.windowingMode == WINDOWING_MODE_FULLSCREEN ||
- taskInfo.windowingMode == WINDOWING_MODE_MULTI_WINDOW) &&
- taskInfo.activityType != ACTIVITY_TYPE_HOME
- }
- if (allFocusedTasks.isNotEmpty()) {
- when (allFocusedTasks.size) {
- 2 -> {
- // Split-screen case where there are two focused tasks, then we find the child
- // task to move to desktop.
- val splitFocusedTask =
- if (allFocusedTasks[0].taskId == allFocusedTasks[1].parentTaskId) {
- allFocusedTasks[1]
- } else {
- allFocusedTasks[0]
- }
- moveToDesktop(splitFocusedTask, transitionSource = transitionSource)
- }
- 1 -> {
- // Fullscreen case where we move the current focused task.
- moveToDesktop(allFocusedTasks[0].taskId, transitionSource = transitionSource)
- }
- else -> logW("Cannot enter desktop, expected < 3 focused tasks, found %d",
- allFocusedTasks.size)
- }
+ val allFocusedTasks = getAllFocusedTasks(displayId)
+ when (allFocusedTasks.size) {
+ 0 -> return
+ // Full screen case
+ 1 -> moveRunningTaskToDesktop(
+ allFocusedTasks.single(), transitionSource = transitionSource)
+ // Split-screen case where there are two focused tasks, then we find the child
+ // task to move to desktop.
+ 2 -> moveRunningTaskToDesktop(
+ getSplitFocusedTask(allFocusedTasks[0], allFocusedTasks[1]),
+ transitionSource = transitionSource)
+ else -> logW(
+ "DesktopTasksController: Cannot enter desktop, expected less " +
+ "than 3 focused tasks but found %d", allFocusedTasks.size)
}
}
- /** Move a task with given `taskId` to desktop */
- fun moveToDesktop(
+ /**
+ * Returns all focused tasks in full screen or split screen mode in [displayId] when
+ * it is not the home activity.
+ */
+ private fun getAllFocusedTasks(displayId: Int): List<RunningTaskInfo> =
+ shellTaskOrganizer.getRunningTasks(displayId).filter {
+ it.isFocused &&
+ (it.windowingMode == WINDOWING_MODE_FULLSCREEN ||
+ it.windowingMode == WINDOWING_MODE_MULTI_WINDOW) &&
+ it.activityType != ACTIVITY_TYPE_HOME
+ }
+
+ /** Returns child task from two focused tasks in split screen mode. */
+ private fun getSplitFocusedTask(task1: RunningTaskInfo, task2: RunningTaskInfo) =
+ if (task1.taskId == task2.parentTaskId) task2 else task1
+
+ /** Moves task to desktop mode if task is running, else launches it in desktop mode. */
+ fun moveTaskToDesktop(
taskId: Int,
wct: WindowContainerTransaction = WindowContainerTransaction(),
transitionSource: DesktopModeTransitionSource,
): Boolean {
- shellTaskOrganizer.getRunningTaskInfo(taskId)?.let {
- moveToDesktop(it, wct, transitionSource)
+ val runningTask = shellTaskOrganizer.getRunningTaskInfo(taskId)
+ if (runningTask == null) {
+ return moveBackgroundTaskToDesktop(taskId, wct, transitionSource)
}
- ?: moveToDesktopFromNonRunningTask(taskId, wct, transitionSource)
+ moveRunningTaskToDesktop(runningTask, wct, transitionSource)
return true
}
- private fun moveToDesktopFromNonRunningTask(
- taskId: Int,
- wct: WindowContainerTransaction,
- transitionSource: DesktopModeTransitionSource,
+ private fun moveBackgroundTaskToDesktop(
+ taskId: Int,
+ wct: WindowContainerTransaction,
+ transitionSource: DesktopModeTransitionSource,
): Boolean {
- recentTasksController?.findTaskInBackground(taskId)?.let {
- logV("moveToDesktopFromNonRunningTask with taskId=%d, displayId=%d", taskId)
- // TODO(342378842): Instead of using default display, support multiple displays
- val taskToMinimize =
- bringDesktopAppsToFrontBeforeShowingNewTask(DEFAULT_DISPLAY, wct, taskId)
- addMoveToDesktopChangesNonRunningTask(wct, taskId)
- // TODO(343149901): Add DPI changes for task launch
- val transition = enterDesktopTaskTransitionHandler.moveToDesktop(wct, transitionSource)
- addPendingMinimizeTransition(transition, taskToMinimize)
- return true
+ if (recentTasksController?.findTaskInBackground(taskId) == null) {
+ logW("moveBackgroundTaskToDesktop taskId=%d not found", taskId)
+ return false
}
- ?: return false
+ logV("moveBackgroundTaskToDesktop with taskId=%d, displayId=%d", taskId)
+ // TODO(342378842): Instead of using default display, support multiple displays
+ val taskToMinimize = bringDesktopAppsToFrontBeforeShowingNewTask(
+ DEFAULT_DISPLAY, wct, taskId)
+ wct.startTask(
+ taskId,
+ ActivityOptions.makeBasic().apply {
+ launchWindowingMode = WINDOWING_MODE_FREEFORM
+ }.toBundle(),
+ )
+ // TODO(343149901): Add DPI changes for task launch
+ val transition = enterDesktopTaskTransitionHandler.moveToDesktop(wct, transitionSource)
+ addPendingMinimizeTransition(transition, taskToMinimize)
+ return true
}
- private fun addMoveToDesktopChangesNonRunningTask(
- wct: WindowContainerTransaction,
- taskId: Int
- ) {
- val options = ActivityOptions.makeBasic()
- options.launchWindowingMode = WINDOWING_MODE_FREEFORM
- wct.startTask(taskId, options.toBundle())
- }
-
- /** Move a task to desktop */
- fun moveToDesktop(
+ /** Moves a running task to desktop. */
+ fun moveRunningTaskToDesktop(
task: RunningTaskInfo,
wct: WindowContainerTransaction = WindowContainerTransaction(),
transitionSource: DesktopModeTransitionSource,
@@ -340,7 +347,7 @@
logW("Cannot enter desktop for taskId %d, ineligible top activity found", task.taskId)
return
}
- logV("moveToDesktop taskId=%d", task.taskId)
+ logV("moveRunningTaskToDesktop taskId=%d", task.taskId)
exitSplitIfApplicable(wct, task)
// Bring other apps to front first
val taskToMinimize =
@@ -638,21 +645,50 @@
/**
* Quick-resize to the right or left half of the stable bounds.
*
+ * @param taskInfo current task that is being snap-resized via dragging or maximize menu button
+ * @param currentDragBounds current position of the task leash being dragged (or current task
+ * bounds if being snapped resize via maximize menu button)
* @param position the portion of the screen (RIGHT or LEFT) we want to snap the task to.
*/
- fun snapToHalfScreen(taskInfo: RunningTaskInfo, position: SnapPosition) {
+ fun snapToHalfScreen(
+ taskInfo: RunningTaskInfo,
+ currentDragBounds: Rect,
+ position: SnapPosition
+ ) {
val destinationBounds = getSnapBounds(taskInfo, position)
if (destinationBounds == taskInfo.configuration.windowConfiguration.bounds) return
val wct = WindowContainerTransaction().setBounds(taskInfo.token, destinationBounds)
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
- toggleResizeDesktopTaskTransitionHandler.startTransition(wct)
+ toggleResizeDesktopTaskTransitionHandler.startTransition(wct, currentDragBounds)
} else {
shellTaskOrganizer.applyTransaction(wct)
}
}
+ @VisibleForTesting
+ fun handleSnapResizingTask(
+ taskInfo: RunningTaskInfo,
+ position: SnapPosition,
+ taskSurface: SurfaceControl,
+ currentDragBounds: Rect,
+ dragStartBounds: Rect
+ ) {
+ releaseVisualIndicator()
+ if (!taskInfo.isResizeable && DesktopModeFlags.DISABLE_SNAP_RESIZE.isEnabled(context)) {
+ // reposition non-resizable app back to its original position before being dragged
+ returnToDragStartAnimator.start(
+ taskInfo.taskId,
+ taskSurface,
+ startBounds = currentDragBounds,
+ endBounds = dragStartBounds
+ )
+ } else {
+ snapToHalfScreen(taskInfo, currentDragBounds, position)
+ }
+ }
+
private fun getDefaultDesktopTaskBounds(displayLayout: DisplayLayout): Rect {
// TODO(b/319819547): Account for app constraints so apps do not become letterboxed
val desiredWidth = (displayLayout.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE).toInt()
@@ -818,8 +854,12 @@
// Check if we should skip handling this transition
var reason = ""
val triggerTask = request.triggerTask
+ var shouldHandleMidRecentsFreeformLaunch =
+ recentsAnimationRunning && isFreeformRelaunch(triggerTask, request)
val shouldHandleRequest =
when {
+ // Handle freeform relaunch during recents animation
+ shouldHandleMidRecentsFreeformLaunch -> true
recentsAnimationRunning -> {
reason = "recents animation is running"
false
@@ -859,6 +899,8 @@
val result =
triggerTask?.let { task ->
when {
+ // Check if freeform task launch during recents should be handled
+ shouldHandleMidRecentsFreeformLaunch -> handleMidRecentsFreeformTaskLaunch(task)
// Check if the closing task needs to be handled
TransitionUtil.isClosingType(request.type) -> handleTaskClosing(task)
// Check if the top task shouldn't be allowed to enter desktop mode
@@ -892,6 +934,12 @@
.forEach { finishTransaction.setCornerRadius(it.leash, cornerRadius) }
}
+ /** Returns whether an existing desktop task is being relaunched in freeform or not. */
+ private fun isFreeformRelaunch(triggerTask: RunningTaskInfo?, request: TransitionRequestInfo) =
+ (triggerTask != null && triggerTask.windowingMode == WINDOWING_MODE_FREEFORM
+ && TransitionUtil.isOpeningType(request.type)
+ && taskRepository.isActiveTask(triggerTask.taskId))
+
private fun isIncompatibleTask(task: TaskInfo) =
DesktopModeFlags.MODALS_POLICY.isEnabled(context)
&& isTopActivityExemptFromDesktopWindowing(context, task)
@@ -902,6 +950,74 @@
request.triggerTask != null
}
+ fun openNewWindow(
+ taskInfo: RunningTaskInfo
+ ) {
+ // TODO(b/337915660): Add a transition handler for these; animations
+ // need updates in some cases.
+ val newTaskWindowingMode = when {
+ taskInfo.isFreeform -> {
+ WINDOWING_MODE_FREEFORM
+ }
+ taskInfo.isFullscreen || taskInfo.isMultiWindow -> {
+ WINDOWING_MODE_MULTI_WINDOW
+ }
+ else -> {
+ error("Invalid windowing mode: ${taskInfo.windowingMode}")
+ }
+ }
+
+ val baseActivity = taskInfo.baseActivity ?: return
+ val fillIn: Intent = context.packageManager
+ .getLaunchIntentForPackage(
+ baseActivity.packageName
+ ) ?: return
+ fillIn
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
+ val options =
+ ActivityOptions.makeBasic().apply {
+ launchWindowingMode = newTaskWindowingMode
+ pendingIntentBackgroundActivityStartMode =
+ ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS
+ }
+ val launchIntent = PendingIntent.getActivity(
+ context,
+ /* requestCode= */ 0,
+ fillIn,
+ PendingIntent.FLAG_IMMUTABLE
+ )
+ when (newTaskWindowingMode) {
+ WINDOWING_MODE_MULTI_WINDOW -> {
+ val splitPosition = splitScreenController.determineNewInstancePosition(taskInfo)
+ splitScreenController.startIntent(
+ launchIntent, context.userId, fillIn, splitPosition,
+ options.toBundle(), null /* hideTaskToken */
+ )
+ }
+ WINDOWING_MODE_FREEFORM -> {
+ // TODO(b/336289597): This currently does not respect the desktop window limit.
+ val wct = WindowContainerTransaction()
+ wct.sendPendingIntent(launchIntent, fillIn, options.toBundle())
+ transitions.startTransition(TRANSIT_OPEN, wct, null)
+ }
+ }
+ }
+
+ /**
+ * Handles the case where a freeform task is launched from recents.
+ *
+ * This is a special case where we want to launch the task in fullscreen instead of freeform.
+ */
+ private fun handleMidRecentsFreeformTaskLaunch(
+ task: RunningTaskInfo
+ ): WindowContainerTransaction? {
+ logV("DesktopTasksController: handleMidRecentsFreeformTaskLaunch")
+ val wct = WindowContainerTransaction()
+ addMoveToFullscreenChanges(wct, task)
+ wct.reorder(task.token, true)
+ return wct
+ }
+
private fun handleFreeformTaskLaunch(
task: RunningTaskInfo,
transition: IBinder
@@ -982,7 +1098,7 @@
}
taskRepository.addClosingTask(task.displayId, task.taskId)
// If a CLOSE or TO_BACK is triggered on a desktop task, remove the task.
- if (Flags.enableDesktopWindowingBackNavigation() &&
+ if (DesktopModeFlags.BACK_NAVIGATION.isEnabled(context) &&
taskRepository.isVisibleTask(task.taskId)) {
wct.removeTask(task.token)
}
@@ -1184,7 +1300,7 @@
taskSurface: SurfaceControl,
inputX: Float,
taskTop: Float
- ): DesktopModeVisualIndicator.IndicatorType {
+ ): IndicatorType {
// If the visual indicator does not exist, create it.
val indicator =
visualIndicator
@@ -1205,16 +1321,22 @@
* that change. Otherwise, ensure bounds are up to date.
*
* @param taskInfo the task being dragged.
+ * @param taskSurface the leash of the task being dragged.
* @param position position of surface when drag ends.
* @param inputCoordinate the coordinates of the motion event
- * @param taskBounds the updated bounds of the task being dragged.
+ * @param currentDragBounds the current bounds of where the visible task is (might be actual
+ * task bounds or just task leash)
+ * @param validDragArea the bounds of where the task can be dragged within the display.
+ * @param dragStartBounds the bounds of the task before starting dragging.
*/
fun onDragPositioningEnd(
taskInfo: RunningTaskInfo,
+ taskSurface: SurfaceControl,
position: Point,
inputCoordinate: PointF,
- taskBounds: Rect,
- validDragArea: Rect
+ currentDragBounds: Rect,
+ validDragArea: Rect,
+ dragStartBounds: Rect,
) {
if (taskInfo.configuration.windowConfiguration.windowingMode != WINDOWING_MODE_FREEFORM) {
return
@@ -1223,41 +1345,44 @@
val indicator = visualIndicator ?: return
val indicatorType =
indicator.updateIndicatorType(
- PointF(inputCoordinate.x, taskBounds.top.toFloat()),
+ PointF(inputCoordinate.x, currentDragBounds.top.toFloat()),
taskInfo.windowingMode
)
when (indicatorType) {
- DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR -> {
+ IndicatorType.TO_FULLSCREEN_INDICATOR -> {
moveToFullscreenWithAnimation(
taskInfo,
position,
DesktopModeTransitionSource.TASK_DRAG
)
}
- DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_LEFT_INDICATOR -> {
- releaseVisualIndicator()
- snapToHalfScreen(taskInfo, SnapPosition.LEFT)
+ IndicatorType.TO_SPLIT_LEFT_INDICATOR -> {
+ handleSnapResizingTask(
+ taskInfo, SnapPosition.LEFT, taskSurface, currentDragBounds, dragStartBounds
+ )
}
- DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_RIGHT_INDICATOR -> {
- releaseVisualIndicator()
- snapToHalfScreen(taskInfo, SnapPosition.RIGHT)
+ IndicatorType.TO_SPLIT_RIGHT_INDICATOR -> {
+ handleSnapResizingTask(
+ taskInfo, SnapPosition.RIGHT, taskSurface, currentDragBounds, dragStartBounds
+ )
}
- DesktopModeVisualIndicator.IndicatorType.NO_INDICATOR -> {
- // If task bounds are outside valid drag area, snap them inward and perform a
- // transaction to set bounds.
- if (
- DragPositioningCallbackUtility.snapTaskBoundsIfNecessary(
- taskBounds,
- validDragArea
- )
- ) {
- val wct = WindowContainerTransaction()
- wct.setBounds(taskInfo.token, taskBounds)
- transitions.startTransition(TRANSIT_CHANGE, wct, null)
- }
+ IndicatorType.NO_INDICATOR -> {
+ // If task bounds are outside valid drag area, snap them inward
+ DragPositioningCallbackUtility.snapTaskBoundsIfNecessary(
+ currentDragBounds,
+ validDragArea
+ )
+
+ if (currentDragBounds == dragStartBounds) return
+
+ // Update task bounds so that the task position will match the position of its leash
+ val wct = WindowContainerTransaction()
+ wct.setBounds(taskInfo.token, currentDragBounds)
+ transitions.startTransition(TRANSIT_CHANGE, wct, null)
+
releaseVisualIndicator()
}
- DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR -> {
+ IndicatorType.TO_DESKTOP_INDICATOR -> {
throw IllegalArgumentException(
"Should not be receiving TO_DESKTOP_INDICATOR for " + "a freeform task."
)
@@ -1488,7 +1613,8 @@
}
override fun hideStashedDesktopApps(displayId: Int) {
- ProtoLog.w(WM_SHELL_DESKTOP_MODE, "IDesktopModeImpl: hideStashedDesktopApps is deprecated")
+ ProtoLog.w(WM_SHELL_DESKTOP_MODE,
+ "IDesktopModeImpl: hideStashedDesktopApps is deprecated")
}
override fun getVisibleTaskCount(displayId: Int): Int {
@@ -1519,8 +1645,8 @@
}
override fun moveToDesktop(taskId: Int, transitionSource: DesktopModeTransitionSource) {
- executeRemoteCallWithTaskPermission(controller, "moveToDesktop") { c ->
- c.moveToDesktop(taskId, transitionSource = transitionSource)
+ executeRemoteCallWithTaskPermission(controller, "moveTaskToDesktop") { c ->
+ c.moveTaskToDesktop(taskId, transitionSource = transitionSource)
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt
index 87d1800..38675129 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt
@@ -17,12 +17,15 @@
package com.android.wm.shell.desktopmode
import android.app.ActivityManager.RunningTaskInfo
+import android.content.Context
import android.os.IBinder
import android.view.SurfaceControl
import android.view.WindowManager.TRANSIT_TO_BACK
import android.window.TransitionInfo
import android.window.WindowContainerTransaction
import androidx.annotation.VisibleForTesting
+import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_MINIMIZE_WINDOW
+import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.protolog.ProtoLog
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.protolog.ShellProtoLogGroup
@@ -41,6 +44,8 @@
private val taskRepository: DesktopModeTaskRepository,
private val shellTaskOrganizer: ShellTaskOrganizer,
private val maxTasksLimit: Int,
+ private val interactionJankMonitor: InteractionJankMonitor,
+ private val context: Context
) {
private val minimizeTransitionObserver = MinimizeTransitionObserver()
@VisibleForTesting
@@ -53,13 +58,20 @@
}
transitions.registerObserver(minimizeTransitionObserver)
taskRepository.addActiveTaskListener(leftoverMinimizedTasksRemover)
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
+ "DesktopTasksLimiter: starting limiter with a maximum of %d tasks", maxTasksLimit)
}
- private data class TaskDetails (val displayId: Int, val taskId: Int)
+ private data class TaskDetails(
+ val displayId: Int,
+ val taskId: Int,
+ var transitionInfo: TransitionInfo?
+ )
// TODO(b/333018485): replace this observer when implementing the minimize-animation
private inner class MinimizeTransitionObserver : TransitionObserver {
private val mPendingTransitionTokensAndTasks = mutableMapOf<IBinder, TaskDetails>()
+ private val mActiveTransitionTokensAndTasks = mutableMapOf<IBinder, TaskDetails>()
fun addPendingTransitionToken(transition: IBinder, taskDetails: TaskDetails) {
mPendingTransitionTokensAndTasks[transition] = taskDetails
@@ -72,6 +84,8 @@
finishTransaction: SurfaceControl.Transaction
) {
val taskToMinimize = mPendingTransitionTokensAndTasks.remove(transition) ?: return
+ taskToMinimize.transitionInfo = info
+ mActiveTransitionTokensAndTasks[transition] = taskToMinimize
if (!taskRepository.isActiveTask(taskToMinimize.taskId)) return
@@ -82,6 +96,7 @@
taskToMinimize.taskId)
return
}
+
this@DesktopTasksLimiter.markTaskMinimized(
taskToMinimize.displayId, taskToMinimize.taskId)
}
@@ -105,9 +120,21 @@
return taskChange.mode == TRANSIT_TO_BACK
}
- override fun onTransitionStarting(transition: IBinder) {}
+ override fun onTransitionStarting(transition: IBinder) {
+ val mActiveTaskDetails = mActiveTransitionTokensAndTasks[transition]
+ if (mActiveTaskDetails != null && mActiveTaskDetails.transitionInfo != null) {
+ // Begin minimize window CUJ instrumentation.
+ interactionJankMonitor.begin(
+ mActiveTaskDetails.transitionInfo?.rootLeash, context,
+ CUJ_DESKTOP_MODE_MINIMIZE_WINDOW
+ )
+ }
+ }
override fun onTransitionMerged(merged: IBinder, playing: IBinder) {
+ if (mActiveTransitionTokensAndTasks.remove(merged) != null) {
+ interactionJankMonitor.end(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)
+ }
mPendingTransitionTokensAndTasks.remove(merged)?.let { taskToTransfer ->
mPendingTransitionTokensAndTasks[playing] = taskToTransfer
}
@@ -117,6 +144,13 @@
ProtoLog.v(
ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
"DesktopTasksLimiter: transition %s finished", transition)
+ if (mActiveTransitionTokensAndTasks.remove(transition) != null) {
+ if (aborted) {
+ interactionJankMonitor.cancel(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)
+ } else {
+ interactionJankMonitor.end(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)
+ }
+ }
mPendingTransitionTokensAndTasks.remove(transition)
}
}
@@ -139,7 +173,9 @@
}
ProtoLog.v(
ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
- "DesktopTasksLimiter: removing leftover minimized tasks: $remainingMinimizedTasks")
+ "DesktopTasksLimiter: removing leftover minimized tasks: %s",
+ remainingMinimizedTasks,
+ )
remainingMinimizedTasks.forEach { taskIdToRemove ->
val taskToRemove = shellTaskOrganizer.getRunningTaskInfo(taskIdToRemove)
if (taskToRemove != null) {
@@ -192,7 +228,7 @@
*/
fun addPendingMinimizeChange(transition: IBinder, displayId: Int, taskId: Int) {
minimizeTransitionObserver.addPendingTransitionToken(
- transition, TaskDetails(displayId, taskId))
+ transition, TaskDetails(displayId, taskId, transitionInfo = null))
}
/**
@@ -219,13 +255,15 @@
// No need to minimize anything
return null
}
+ val taskIdToMinimize = visibleFreeformTaskIdsOrderedFrontToBack.last()
val taskToMinimize =
- shellTaskOrganizer.getRunningTaskInfo(
- visibleFreeformTaskIdsOrderedFrontToBack.last())
+ shellTaskOrganizer.getRunningTaskInfo(taskIdToMinimize)
if (taskToMinimize == null) {
ProtoLog.e(
ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
- "DesktopTasksLimiter: taskToMinimize == null")
+ "DesktopTasksLimiter: taskToMinimize(taskId = %d) == null",
+ taskIdToMinimize,
+ )
return null
}
return taskToMinimize
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
index 9e79eddb0..5221a45 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
@@ -29,10 +29,10 @@
import android.window.TransitionRequestInfo
import android.window.WindowContainerToken
import android.window.WindowContainerTransaction
-import com.android.internal.protolog.ProtoLog
import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG_HOLD
import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG_RELEASE
import com.android.internal.jank.InteractionJankMonitor
+import com.android.internal.protolog.ProtoLog
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT
import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT
@@ -220,16 +220,18 @@
startCancelAnimation()
} else if (
state.draggedTaskChange != null &&
- (cancelState == CancelState.CANCEL_SPLIT_LEFT ||
+ (cancelState == CancelState.CANCEL_SPLIT_LEFT ||
cancelState == CancelState.CANCEL_SPLIT_RIGHT)
- ) {
+ ) {
// We have a valid dragged task, but the animation will be handled by
// SplitScreenController; request the transition here.
- @SplitPosition val splitPosition = if (cancelState == CancelState.CANCEL_SPLIT_LEFT) {
- SPLIT_POSITION_TOP_OR_LEFT
- } else {
- SPLIT_POSITION_BOTTOM_OR_RIGHT
- }
+ @SplitPosition
+ val splitPosition =
+ if (cancelState == CancelState.CANCEL_SPLIT_LEFT) {
+ SPLIT_POSITION_TOP_OR_LEFT
+ } else {
+ SPLIT_POSITION_BOTTOM_OR_RIGHT
+ }
val wct = WindowContainerTransaction()
restoreWindowOrder(wct, state)
state.startTransitionFinishTransaction?.apply()
@@ -252,20 +254,20 @@
wct: WindowContainerTransaction
) {
val state = requireTransitionState()
- val taskInfo = state.draggedTaskChange?.taskInfo
- ?: error("Expected non-null taskInfo")
+ val taskInfo = state.draggedTaskChange?.taskInfo ?: error("Expected non-null taskInfo")
val taskBounds = Rect(taskInfo.configuration.windowConfiguration.bounds)
val taskScale = state.dragAnimator.scale
val scaledWidth = taskBounds.width() * taskScale
val scaledHeight = taskBounds.height() * taskScale
val dragPosition = PointF(state.dragAnimator.position)
state.dragAnimator.cancelAnimator()
- val animatedTaskBounds = Rect(
- dragPosition.x.toInt(),
- dragPosition.y.toInt(),
- (dragPosition.x + scaledWidth).toInt(),
- (dragPosition.y + scaledHeight).toInt()
- )
+ val animatedTaskBounds =
+ Rect(
+ dragPosition.x.toInt(),
+ dragPosition.y.toInt(),
+ (dragPosition.x + scaledWidth).toInt(),
+ (dragPosition.y + scaledHeight).toInt()
+ )
requestSplitSelect(wct, taskInfo, splitPosition, animatedTaskBounds)
}
@@ -286,12 +288,7 @@
}
wct.setWindowingMode(taskInfo.token, WINDOWING_MODE_MULTI_WINDOW)
wct.setDensityDpi(taskInfo.token, context.resources.displayMetrics.densityDpi)
- splitScreenController.requestEnterSplitSelect(
- taskInfo,
- wct,
- splitPosition,
- taskBounds
- )
+ splitScreenController.requestEnterSplitSelect(taskInfo, wct, splitPosition, taskBounds)
}
override fun startAnimation(
@@ -390,7 +387,7 @@
// occurred.
if (
change.taskInfo?.taskId == state.draggedTaskId &&
- state.cancelState != CancelState.STANDARD_CANCEL
+ state.cancelState != CancelState.STANDARD_CANCEL
) {
// We need access to the dragged task's change in both non-cancel and split
// cancel cases.
@@ -398,8 +395,8 @@
}
if (
change.taskInfo?.taskId == state.draggedTaskId &&
- state.cancelState == CancelState.NO_CANCEL
- ) {
+ state.cancelState == CancelState.NO_CANCEL
+ ) {
taskDisplayAreaOrganizer.reparentToDisplayArea(
change.endDisplayId,
change.leash,
@@ -432,19 +429,20 @@
startCancelDragToDesktopTransition()
} else if (
state.cancelState == CancelState.CANCEL_SPLIT_LEFT ||
- state.cancelState == CancelState.CANCEL_SPLIT_RIGHT
- ){
+ state.cancelState == CancelState.CANCEL_SPLIT_RIGHT
+ ) {
// Cancel-early case for split-cancel. The state was flagged already as a cancel for
// requesting split select. Similar to the above, this can happen due to quick fling
// gestures. We can simply request split here without needing to calculate animated
// task bounds as the task has not shrunk at all.
- val splitPosition = if (state.cancelState == CancelState.CANCEL_SPLIT_LEFT) {
- SPLIT_POSITION_TOP_OR_LEFT
- } else {
- SPLIT_POSITION_BOTTOM_OR_RIGHT
- }
- val taskInfo = state.draggedTaskChange?.taskInfo
- ?: error("Expected non-null task info.")
+ val splitPosition =
+ if (state.cancelState == CancelState.CANCEL_SPLIT_LEFT) {
+ SPLIT_POSITION_TOP_OR_LEFT
+ } else {
+ SPLIT_POSITION_BOTTOM_OR_RIGHT
+ }
+ val taskInfo =
+ state.draggedTaskChange?.taskInfo ?: error("Expected non-null task info.")
val wct = WindowContainerTransaction()
restoreWindowOrder(wct)
state.startTransitionFinishTransaction?.apply()
@@ -463,8 +461,10 @@
) {
val state = requireTransitionState()
// We don't want to merge the split select animation if that's what we requested.
- if (state.cancelState == CancelState.CANCEL_SPLIT_LEFT ||
- state.cancelState == CancelState.CANCEL_SPLIT_RIGHT) {
+ if (
+ state.cancelState == CancelState.CANCEL_SPLIT_LEFT ||
+ state.cancelState == CancelState.CANCEL_SPLIT_RIGHT
+ ) {
clearState()
return
}
@@ -574,7 +574,8 @@
startTransitionFinishCb.onTransitionFinished(null /* null */)
clearState()
interactionJankMonitor.end(
- CUJ_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG_RELEASE)
+ CUJ_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG_RELEASE
+ )
}
}
)
@@ -673,9 +674,7 @@
val wct = WindowContainerTransaction()
restoreWindowOrder(wct, state)
state.cancelTransitionToken =
- transitions.startTransition(
- TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP, wct, this
- )
+ transitions.startTransition(TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP, wct, this)
}
private fun restoreWindowOrder(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ReturnToDragStartAnimator.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ReturnToDragStartAnimator.kt
new file mode 100644
index 0000000..be67a40
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ReturnToDragStartAnimator.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.desktopmode
+
+import android.animation.Animator
+import android.animation.RectEvaluator
+import android.animation.ValueAnimator
+import android.graphics.Rect
+import android.view.SurfaceControl
+import androidx.core.animation.addListener
+import com.android.internal.jank.InteractionJankMonitor
+import com.android.wm.shell.windowdecor.OnTaskRepositionAnimationListener
+import java.util.function.Supplier
+
+/** Animates the task surface moving from its current drag position to its pre-drag position. */
+class ReturnToDragStartAnimator(
+ private val transactionSupplier: Supplier<SurfaceControl.Transaction>,
+ private val interactionJankMonitor: InteractionJankMonitor
+) {
+ private var boundsAnimator: Animator? = null
+ private lateinit var taskRepositionAnimationListener: OnTaskRepositionAnimationListener
+
+ constructor(interactionJankMonitor: InteractionJankMonitor) :
+ this(Supplier { SurfaceControl.Transaction() }, interactionJankMonitor)
+
+ /** Sets a listener for the start and end of the reposition animation. */
+ fun setTaskRepositionAnimationListener(listener: OnTaskRepositionAnimationListener) {
+ taskRepositionAnimationListener = listener
+ }
+
+ /** Builds new animator and starts animation of task leash reposition. */
+ fun start(taskId: Int, taskSurface: SurfaceControl, startBounds: Rect, endBounds: Rect) {
+ val tx = transactionSupplier.get()
+
+ boundsAnimator?.cancel()
+ boundsAnimator =
+ ValueAnimator.ofObject(RectEvaluator(), startBounds, endBounds)
+ .setDuration(RETURN_TO_DRAG_START_ANIMATION_MS)
+ .apply {
+ addListener(
+ onStart = {
+ val startTransaction = transactionSupplier.get()
+ startTransaction
+ .setPosition(
+ taskSurface,
+ startBounds.left.toFloat(),
+ startBounds.top.toFloat()
+ )
+ .show(taskSurface)
+ .apply()
+ taskRepositionAnimationListener.onAnimationStart(taskId)
+ },
+ onEnd = {
+ val finishTransaction = transactionSupplier.get()
+ finishTransaction
+ .setPosition(
+ taskSurface,
+ endBounds.left.toFloat(),
+ endBounds.top.toFloat()
+ )
+ .show(taskSurface)
+ .apply()
+ taskRepositionAnimationListener.onAnimationEnd(taskId)
+ boundsAnimator = null
+ // TODO(b/354658237) - show toast with relevant string
+ // TODO(b/339582583) - add Jank CUJ using interactionJankMonitor
+ }
+ )
+ addUpdateListener { anim ->
+ val rect = anim.animatedValue as Rect
+ tx.setPosition(taskSurface, rect.left.toFloat(), rect.top.toFloat())
+ .show(taskSurface)
+ .apply()
+ }
+ }
+ .also(ValueAnimator::start)
+ }
+
+ companion object {
+ const val RETURN_TO_DRAG_START_ANIMATION_MS = 300L
+ }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ToggleResizeDesktopTaskTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ToggleResizeDesktopTaskTransitionHandler.kt
index c35d77a..bf185a4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ToggleResizeDesktopTaskTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ToggleResizeDesktopTaskTransitionHandler.kt
@@ -45,15 +45,24 @@
private lateinit var onTaskResizeAnimationListener: OnTaskResizeAnimationListener
private var boundsAnimator: Animator? = null
+ private var initialBounds: Rect? = null
constructor(
transitions: Transitions,
interactionJankMonitor: InteractionJankMonitor
) : this(transitions, Supplier { SurfaceControl.Transaction() }, interactionJankMonitor)
- /** Starts a quick resize transition. */
- fun startTransition(wct: WindowContainerTransaction) {
+ /**
+ * Starts a quick resize transition.
+ *
+ * @param wct WindowContainerTransaction that will update core about the task changes applied
+ * @param taskLeashBounds current bounds of the task leash (Note: not guaranteed to be the
+ * bounds of the actual task). This is provided so that the animation
+ * resizing can begin where the task leash currently is for smoother UX.
+ */
+ fun startTransition(wct: WindowContainerTransaction, taskLeashBounds: Rect? = null) {
transitions.startTransition(TRANSIT_DESKTOP_MODE_TOGGLE_RESIZE, wct, this)
+ initialBounds = taskLeashBounds
}
fun setOnTaskResizeAnimationListener(listener: OnTaskResizeAnimationListener) {
@@ -70,7 +79,7 @@
val change = findRelevantChange(info)
val leash = change.leash
val taskId = checkNotNull(change.taskInfo).taskId
- val startBounds = change.startAbsBounds
+ val startBounds = initialBounds ?: change.startAbsBounds
val endBounds = change.endAbsBounds
val tx = transactionSupplier.get()
@@ -92,7 +101,7 @@
onTaskResizeAnimationListener.onAnimationStart(
taskId,
startTransaction,
- startBounds
+ startBounds,
)
},
onEnd = {
@@ -106,6 +115,7 @@
.show(leash)
onTaskResizeAnimationListener.onAnimationEnd(taskId)
finishCallback.onTransitionFinished(null)
+ initialBounds = null
boundsAnimator = null
interactionJankMonitor.end(
Cuj.CUJ_DESKTOP_MODE_MAXIMIZE_WINDOW)
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 229d972..456767a 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
@@ -99,11 +99,10 @@
if (DesktopModeStatus.canEnterDesktopMode(mContext)) {
mDesktopModeTaskRepository.ifPresent(repository -> {
repository.addOrMoveFreeformTaskToTop(taskInfo.displayId, taskInfo.taskId);
- repository.unminimizeTask(taskInfo.displayId, taskInfo.taskId);
if (taskInfo.isVisible) {
repository.addActiveTask(taskInfo.displayId, taskInfo.taskId);
- repository.updateVisibleFreeformTasks(taskInfo.displayId, taskInfo.taskId,
- true);
+ repository.updateTaskVisibility(taskInfo.displayId, taskInfo.taskId,
+ /* visible= */ true);
}
});
}
@@ -118,9 +117,6 @@
if (DesktopModeStatus.canEnterDesktopMode(mContext)) {
mDesktopModeTaskRepository.ifPresent(repository -> {
repository.removeFreeformTask(taskInfo.displayId, taskInfo.taskId);
- repository.unminimizeTask(taskInfo.displayId, taskInfo.taskId);
- repository.removeActiveTask(taskInfo.taskId, /* excludedDisplayId= */ null);
- repository.updateVisibleFreeformTasks(taskInfo.displayId, taskInfo.taskId, false);
});
}
mWindowDecorationViewModel.onTaskVanished(taskInfo);
@@ -144,7 +140,7 @@
} else if (repository.isClosingTask(taskInfo.taskId)) {
repository.removeClosingTask(taskInfo.taskId);
}
- repository.updateVisibleFreeformTasks(taskInfo.displayId, taskInfo.taskId,
+ repository.updateTaskVisibility(taskInfo.displayId, taskInfo.taskId,
taskInfo.isVisible);
});
}
@@ -161,7 +157,6 @@
if (DesktopModeStatus.canEnterDesktopMode(mContext) && taskInfo.isFocused) {
mDesktopModeTaskRepository.ifPresent(repository -> {
repository.addOrMoveFreeformTaskToTop(taskInfo.displayId, taskInfo.taskId);
- repository.unminimizeTask(taskInfo.displayId, taskInfo.taskId);
});
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
index 94fe286..7774384 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
@@ -300,6 +300,10 @@
int launcherRotation, Rect hotseatKeepClearArea) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"getSwipePipToHomeBounds: %s", componentName);
+ // preemptively add the keep clear area for Hotseat, so that it is taken into account
+ // when calculating the entry destination bounds of PiP window
+ mPipBoundsState.setNamedUnrestrictedKeepClearArea(
+ PipBoundsState.NAMED_KCA_LAUNCHER_SHELF, hotseatKeepClearArea);
mPipBoundsState.setBoundsStateForEntry(componentName, activityInfo, pictureInPictureParams,
mPipBoundsAlgorithm);
return mPipBoundsAlgorithm.getEntryDestinationBounds();
@@ -328,6 +332,23 @@
mPipRecentsAnimationListener.onPipAnimationStarted();
}
+ private void setLauncherKeepClearAreaHeight(boolean visible, int height) {
+ ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+ "setLauncherKeepClearAreaHeight: visible=%b, height=%d", visible, height);
+ if (visible) {
+ Rect rect = new Rect(
+ 0, mPipDisplayLayoutState.getDisplayBounds().bottom - height,
+ mPipDisplayLayoutState.getDisplayBounds().right,
+ mPipDisplayLayoutState.getDisplayBounds().bottom);
+ mPipBoundsState.setNamedUnrestrictedKeepClearArea(
+ PipBoundsState.NAMED_KCA_LAUNCHER_SHELF, rect);
+ } else {
+ mPipBoundsState.setNamedUnrestrictedKeepClearArea(
+ PipBoundsState.NAMED_KCA_LAUNCHER_SHELF, null);
+ }
+ mPipTouchHandler.onShelfVisibilityChanged(visible, height);
+ }
+
@Override
public void onPipTransitionStateChanged(@PipTransitionState.TransitionState int oldState,
@PipTransitionState.TransitionState int newState, @Nullable Bundle extra) {
@@ -349,10 +370,14 @@
if (mPipTransitionState.isInSwipePipToHomeTransition()) {
mPipTransitionState.resetSwipePipToHomeState();
}
- mOnIsInPipStateChangedListener.accept(true /* inPip */);
+ if (mOnIsInPipStateChangedListener != null) {
+ mOnIsInPipStateChangedListener.accept(true /* inPip */);
+ }
break;
case PipTransitionState.EXITED_PIP:
- mOnIsInPipStateChangedListener.accept(false /* inPip */);
+ if (mOnIsInPipStateChangedListener != null) {
+ mOnIsInPipStateChangedListener.accept(false /* inPip */);
+ }
break;
}
}
@@ -499,7 +524,10 @@
public void setShelfHeight(boolean visible, int height) {}
@Override
- public void setLauncherKeepClearAreaHeight(boolean visible, int height) {}
+ public void setLauncherKeepClearAreaHeight(boolean visible, int height) {
+ executeRemoteCallWithTaskPermission(mController, "setLauncherKeepClearAreaHeight",
+ (controller) -> controller.setLauncherKeepClearAreaHeight(visible, height));
+ }
@Override
public void setLauncherAppIconSize(int iconSizePx) {}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java
index f387e72..d7c225b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java
@@ -38,6 +38,7 @@
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Bundle;
+import android.os.SystemProperties;
import android.provider.DeviceConfig;
import android.util.Size;
import android.view.DisplayCutout;
@@ -78,6 +79,8 @@
private static final String TAG = "PipTouchHandler";
private static final float DEFAULT_STASH_VELOCITY_THRESHOLD = 18000.f;
+ private static final long PIP_KEEP_CLEAR_AREAS_DELAY =
+ SystemProperties.getLong("persist.wm.debug.pip_keep_clear_areas_delay", 200);
// Allow PIP to resize to a slightly bigger state upon touch
private boolean mEnableResize;
@@ -134,6 +137,10 @@
// Temp vars
private final Rect mTmpBounds = new Rect();
+ // Callbacks
+ private final Runnable mMoveOnShelVisibilityChanged;
+
+
/**
* A listener for the PIP menu activity.
*/
@@ -217,6 +224,26 @@
mPipPerfHintController);
mPipBoundsState.addOnAspectRatioChangedCallback(this::updateMinMaxSize);
+ mMoveOnShelVisibilityChanged = () -> {
+ if (mIsImeShowing && mImeHeight > mShelfHeight) {
+ // Early bail-out if IME is visible with a larger height present;
+ // this should block unnecessary PiP movement since we delay checking for
+ // KCA triggered movement to wait for other transitions (e.g. due to IME changes).
+ return;
+ }
+ mPipTransitionState.setOnIdlePipTransitionStateRunnable(() -> {
+ boolean hasUserInteracted = (mPipBoundsState.hasUserMovedPip()
+ || mPipBoundsState.hasUserResizedPip());
+ int delta = mPipBoundsAlgorithm.getEntryDestinationBounds().top
+ - mPipBoundsState.getBounds().top;
+
+ if (!mIsImeShowing && !hasUserInteracted && delta != 0) {
+ // If the user hasn't interacted with PiP, we respect the keep clear areas
+ mMotionHelper.animateToOffset(mPipBoundsState.getBounds(), delta);
+ }
+ });
+ };
+
if (PipUtils.isPip2ExperimentEnabled()) {
shellInit.addInitCallback(this::onInit, this);
}
@@ -356,9 +383,14 @@
mPipTransitionState.setOnIdlePipTransitionStateRunnable(() -> {
int delta = mPipBoundsState.getMovementBounds().bottom
- mPipBoundsState.getBounds().top;
-
boolean hasUserInteracted = (mPipBoundsState.hasUserMovedPip()
|| mPipBoundsState.hasUserResizedPip());
+
+ if (!imeVisible && !hasUserInteracted) {
+ delta = mPipBoundsAlgorithm.getEntryDestinationBounds().top
+ - mPipBoundsState.getBounds().top;
+ }
+
if ((imeVisible && delta < 0) || (!imeVisible && !hasUserInteracted)) {
// The policy is to ignore an IME disappearing if user has interacted with PiP.
// Otherwise, only offset due to an appearing IME if PiP occludes it.
@@ -370,6 +402,16 @@
void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) {
mIsShelfShowing = shelfVisible;
mShelfHeight = shelfHeight;
+
+ // We need to remove the callback even if the shelf is visible, in case it the delayed
+ // callback hasn't been executed yet to avoid the wrong final state.
+ mMainExecutor.removeCallbacks(mMoveOnShelVisibilityChanged);
+ if (shelfVisible) {
+ mMoveOnShelVisibilityChanged.run();
+ } else {
+ // Postpone moving in response to hide of Launcher in case there's another change
+ mMainExecutor.executeDelayed(mMoveOnShelVisibilityChanged, PIP_KEEP_CLEAR_AREAS_DELAY);
+ }
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
index 33703ad..7790c51 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
@@ -108,10 +108,6 @@
//
@Nullable
- private WindowContainerToken mPipTaskToken;
- @Nullable
- private SurfaceControl mPipLeash;
- @Nullable
private Transitions.TransitionFinishCallback mFinishCallback;
public PipTransition(
@@ -402,7 +398,6 @@
finishWct.setBoundsChangeTransaction(pipTaskToken, tx);
animator.setAnimationEndCallback(() -> {
- mPipTransitionState.setState(PipTransitionState.ENTERED_PIP);
finishCallback.onTransitionFinished(finishWct.isEmpty() ? null : finishWct);
});
@@ -444,15 +439,16 @@
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
- TransitionInfo.Change pipChange = getPipChange(info);
+ WindowContainerToken pipToken = mPipTransitionState.mPipTaskToken;
+
+ TransitionInfo.Change pipChange = getChangeByToken(info, pipToken);
if (pipChange == null) {
return false;
}
Rect startBounds = pipChange.getStartAbsBounds();
Rect endBounds = pipChange.getEndAbsBounds();
- SurfaceControl pipLeash = mPipTransitionState.mPinnedTaskLeash;
- Preconditions.checkNotNull(pipLeash, "Leash is null for bounds transition.");
+ SurfaceControl pipLeash = pipChange.getLeash();
PipEnterExitAnimator animator = new PipEnterExitAnimator(mContext, pipLeash,
startTransaction, startBounds, startBounds, endBounds,
@@ -491,6 +487,18 @@
return null;
}
+ @Nullable
+ private TransitionInfo.Change getChangeByToken(TransitionInfo info,
+ WindowContainerToken token) {
+ for (TransitionInfo.Change change : info.getChanges()) {
+ if (change.getTaskInfo() != null
+ && change.getTaskInfo().getToken().equals(token)) {
+ return change;
+ }
+ }
+ return null;
+ }
+
private WindowContainerTransaction getEnterPipTransaction(@NonNull IBinder transition,
@NonNull TransitionRequestInfo request) {
// cache the original task token to check for multi-activity case later
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 54f908b..da7e03f 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
@@ -19,7 +19,6 @@
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.content.pm.PackageManager.FEATURE_PC;
-import static com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_RECENT_TASKS;
import android.app.ActivityManager;
@@ -365,7 +364,7 @@
private boolean shouldEnableRunningTasksForDesktopMode() {
return mPcFeatureEnabled
|| (DesktopModeStatus.canEnterDesktopMode(mContext)
- && enableDesktopWindowingTaskbarRunningApps());
+ && DesktopModeFlags.TASKBAR_RUNNING_APPS.isEnabled(mContext));
}
@VisibleForTesting
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
index 234b4d0..ad3f4f8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
@@ -19,12 +19,14 @@
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.WindowManager.KEYGUARD_VISIBILITY_TRANSIT_FLAGS;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
import static android.view.WindowManager.TRANSIT_PIP;
import static android.view.WindowManager.TRANSIT_SLEEP;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
+import static android.window.TransitionInfo.FLAG_MOVED_TO_TOP;
import static android.window.TransitionInfo.FLAG_TRANSLUCENT;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_CAN_HAND_OFF_ANIMATION;
@@ -775,6 +777,20 @@
// Don't consider order-only & non-leaf changes as changing apps.
if (!TransitionUtil.isOrderOnly(change) && isLeafTask) {
hasChangingApp = true;
+ // Check if the changing app is moving to top and fullscreen. This handles
+ // the case where we moved from desktop to recents and launching a desktop
+ // task in fullscreen.
+ if ((change.getFlags() & FLAG_MOVED_TO_TOP) != 0
+ && taskInfo != null
+ && taskInfo.getWindowingMode()
+ == WINDOWING_MODE_FULLSCREEN) {
+ if (openingTasks == null) {
+ openingTasks = new ArrayList<>();
+ openingTaskIsLeafs = new IntArray();
+ }
+ openingTasks.add(change);
+ openingTaskIsLeafs.add(1);
+ }
} else if (isLeafTask && taskInfo.topActivityType == ACTIVITY_TYPE_HOME
&& !isRecentsTask ) {
// Unless it is a 3p launcher. This means that the 3p launcher was already
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 0ca244c..59aa792 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
@@ -109,35 +109,6 @@
in RemoteTransition remoteTransition, in InstanceId instanceId) = 17;
/**
- * Version of startTasks using legacy transition system.
- */
- oneway void startTasksWithLegacyTransition(int taskId1, in Bundle options1, int taskId2,
- in Bundle options2, int splitPosition, int snapPosition,
- in RemoteAnimationAdapter adapter, in InstanceId instanceId) = 11;
-
- /**
- * Starts a pair of intent and task using legacy transition system.
- */
- oneway void startIntentAndTaskWithLegacyTransition(in PendingIntent pendingIntent, int userId1,
- in Bundle options1, int taskId, in Bundle options2, int splitPosition, int snapPosition,
- in RemoteAnimationAdapter adapter, in InstanceId instanceId) = 12;
-
- /**
- * Starts a pair of shortcut and task using legacy transition system.
- */
- oneway void startShortcutAndTaskWithLegacyTransition(in ShortcutInfo shortcutInfo,
- in Bundle options1, int taskId, in Bundle options2, int splitPosition, int snapPosition,
- in RemoteAnimationAdapter adapter, in InstanceId instanceId) = 15;
-
- /**
- * Start a pair of intents using legacy transition system.
- */
- oneway void startIntentsWithLegacyTransition(in PendingIntent pendingIntent1, int userId1,
- in ShortcutInfo shortcutInfo1, in Bundle options1, in PendingIntent pendingIntent2,
- int userId2, in ShortcutInfo shortcutInfo2, in Bundle options2, int splitPosition,
- int snapPosition, in RemoteAnimationAdapter adapter, in InstanceId instanceId) = 18;
-
- /**
* Start a pair of intents in one transition.
*/
oneway void startIntents(in PendingIntent pendingIntent1, int userId1,
@@ -146,20 +117,6 @@
int snapPosition, in RemoteTransition remoteTransition, in InstanceId instanceId) = 19;
/**
- * Blocking call that notifies and gets additional split-screen targets when entering
- * recents (for example: the dividerBar).
- * @param appTargets apps that will be re-parented to display area
- */
- RemoteAnimationTarget[] onGoingToRecentsLegacy(in RemoteAnimationTarget[] appTargets) = 13;
-
- /**
- * Blocking call that notifies and gets additional split-screen targets when entering
- * recents (for example: the dividerBar). Different than the method above in that this one
- * does not expect split to currently be running.
- */
- RemoteAnimationTarget[] onStartingSplitLegacy(in RemoteAnimationTarget[] appTargets) = 14;
-
- /**
* Reverse the split.
*/
oneway void switchSplitPosition() = 22;
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 b857556..83f827a 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
@@ -19,10 +19,10 @@
import static android.app.ActivityManager.START_SUCCESS;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static com.android.wm.shell.common.MultiInstanceHelper.getComponent;
import static com.android.wm.shell.common.MultiInstanceHelper.getShortcutComponent;
@@ -34,9 +34,9 @@
import static com.android.wm.shell.common.split.SplitScreenUtils.isValidToSplit;
import static com.android.wm.shell.common.split.SplitScreenUtils.reverseSplitPosition;
import static com.android.wm.shell.common.split.SplitScreenUtils.splitFailureMessage;
+import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_SPLIT_SCREEN;
-import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
import android.app.ActivityManager;
import android.app.ActivityOptions;
@@ -200,11 +200,6 @@
@VisibleForTesting
StageCoordinator mStageCoordinator;
- // Only used for the legacy recents animation from splitscreen to allow the tasks to be animated
- // outside the bounds of the roots by being reparented into a higher level fullscreen container
- private SurfaceControl mGoingToRecentsTasksLayer;
- private SurfaceControl mStartingSplitTasksLayer;
-
/**
* @param stageCoordinator if null, a stage coordinator will be created when this controller is
* initialized. Can be non-null for testing purposes.
@@ -431,6 +426,20 @@
mStageCoordinator.clearSplitPairedInRecents(reason);
}
+ /**
+ * Determines which split position a new instance of a task should take.
+ * @param callingTask The task requesting a new instance.
+ * @return the split position of the new instance
+ */
+ public int determineNewInstancePosition(@NonNull ActivityManager.RunningTaskInfo callingTask) {
+ if (callingTask.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
+ || getSplitPosition(callingTask.taskId) == SPLIT_POSITION_TOP_OR_LEFT) {
+ return SPLIT_POSITION_BOTTOM_OR_RIGHT;
+ } else {
+ return SPLIT_POSITION_TOP_OR_LEFT;
+ }
+ }
+
public void enterSplitScreen(int taskId, boolean leftOrTop) {
enterSplitScreen(taskId, leftOrTop, new WindowContainerTransaction());
}
@@ -442,11 +451,7 @@
}
public void exitSplitScreen(int toTopTaskId, @ExitReason int exitReason) {
- if (ENABLE_SHELL_TRANSITIONS) {
- mStageCoordinator.dismissSplitScreen(toTopTaskId, exitReason);
- } else {
- mStageCoordinator.exitSplitScreen(toTopTaskId, exitReason);
- }
+ mStageCoordinator.dismissSplitScreen(toTopTaskId, exitReason);
}
@Override
@@ -591,7 +596,8 @@
*/
public void startShortcut(String packageName, String shortcutId, @SplitPosition int position,
@Nullable Bundle options, UserHandle user, @NonNull InstanceId instanceId) {
- mStageCoordinator.onRequestToSplit(instanceId, ENTER_REASON_LAUNCHER);
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "startShortcut: reason=%d", ENTER_REASON_LAUNCHER);
+ mStageCoordinator.getLogger().enterRequested(instanceId, ENTER_REASON_LAUNCHER);
startShortcut(packageName, shortcutId, position, options, user);
}
@@ -625,37 +631,6 @@
activityOptions.toBundle(), user);
}
- void startShortcutAndTaskWithLegacyTransition(@NonNull ShortcutInfo shortcutInfo,
- @Nullable Bundle options1, int taskId, @Nullable Bundle options2,
- @SplitPosition int splitPosition, @PersistentSnapPosition int snapPosition,
- RemoteAnimationAdapter adapter, InstanceId instanceId) {
- if (options1 == null) options1 = new Bundle();
- final ActivityOptions activityOptions = ActivityOptions.fromBundle(options1);
-
- final String packageName1 = shortcutInfo.getPackage();
- final String packageName2 = SplitScreenUtils.getPackageName(taskId, mTaskOrganizer);
- final int userId1 = shortcutInfo.getUserId();
- final int userId2 = SplitScreenUtils.getUserId(taskId, mTaskOrganizer);
- if (samePackage(packageName1, packageName2, userId1, userId2)) {
- if (mMultiInstanceHelpher.supportsMultiInstanceSplit(shortcutInfo.getActivity())) {
- activityOptions.setApplyMultipleTaskFlagForShortcut(true);
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
- } else {
- taskId = INVALID_TASK_ID;
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
- "Cancel entering split as not supporting multi-instances");
- Log.w(TAG, splitFailureMessage("startShortcutAndTaskWithLegacyTransition",
- "app package " + packageName1 + " does not support multi-instance"));
- Toast.makeText(mContext, R.string.dock_multi_instances_not_supported_text,
- Toast.LENGTH_SHORT).show();
- }
- }
-
- mStageCoordinator.startShortcutAndTaskWithLegacyTransition(shortcutInfo,
- activityOptions.toBundle(), taskId, options2, splitPosition, snapPosition, adapter,
- instanceId);
- }
-
void startShortcutAndTask(@NonNull ShortcutInfo shortcutInfo, @Nullable Bundle options1,
int taskId, @Nullable Bundle options2, @SplitPosition int splitPosition,
@PersistentSnapPosition int snapPosition, @Nullable RemoteTransition remoteTransition,
@@ -696,37 +671,12 @@
public void startIntentWithInstanceId(PendingIntent intent, int userId,
@Nullable Intent fillInIntent, @SplitPosition int position, @Nullable Bundle options,
@NonNull InstanceId instanceId) {
- mStageCoordinator.onRequestToSplit(instanceId, ENTER_REASON_LAUNCHER);
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "startIntentWithInstanceId: reason=%d",
+ ENTER_REASON_LAUNCHER);
+ mStageCoordinator.getLogger().enterRequested(instanceId, ENTER_REASON_LAUNCHER);
startIntent(intent, userId, fillInIntent, position, options, null /* hideTaskToken */);
}
- private void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent, int userId1,
- @Nullable Bundle options1, int taskId, @Nullable Bundle options2,
- @SplitPosition int splitPosition, @PersistentSnapPosition int snapPosition,
- RemoteAnimationAdapter adapter, InstanceId instanceId) {
- Intent fillInIntent = null;
- final String packageName1 = SplitScreenUtils.getPackageName(pendingIntent);
- final String packageName2 = SplitScreenUtils.getPackageName(taskId, mTaskOrganizer);
- final int userId2 = SplitScreenUtils.getUserId(taskId, mTaskOrganizer);
- if (samePackage(packageName1, packageName2, userId1, userId2)) {
- if (mMultiInstanceHelpher.supportsMultiInstanceSplit(getComponent(pendingIntent))) {
- fillInIntent = new Intent();
- fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
- } else {
- taskId = INVALID_TASK_ID;
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
- "Cancel entering split as not supporting multi-instances");
- Log.w(TAG, splitFailureMessage("startIntentAndTaskWithLegacyTransition",
- "app package " + packageName1 + " does not support multi-instance"));
- Toast.makeText(mContext, R.string.dock_multi_instances_not_supported_text,
- Toast.LENGTH_SHORT).show();
- }
- }
- mStageCoordinator.startIntentAndTaskWithLegacyTransition(pendingIntent, fillInIntent,
- options1, taskId, options2, splitPosition, snapPosition, adapter, instanceId);
- }
-
private void startIntentAndTask(PendingIntent pendingIntent, int userId1,
@Nullable Bundle options1, int taskId, @Nullable Bundle options2,
@SplitPosition int splitPosition, @PersistentSnapPosition int snapPosition,
@@ -763,38 +713,6 @@
options2, splitPosition, snapPosition, remoteTransition, instanceId);
}
- private void startIntentsWithLegacyTransition(PendingIntent pendingIntent1, int userId1,
- @Nullable ShortcutInfo shortcutInfo1, @Nullable Bundle options1,
- PendingIntent pendingIntent2, int userId2, @Nullable ShortcutInfo shortcutInfo2,
- @Nullable Bundle options2, @SplitPosition int splitPosition,
- @PersistentSnapPosition int snapPosition, RemoteAnimationAdapter adapter,
- InstanceId instanceId) {
- Intent fillInIntent1 = null;
- Intent fillInIntent2 = null;
- final String packageName1 = SplitScreenUtils.getPackageName(pendingIntent1);
- final String packageName2 = SplitScreenUtils.getPackageName(pendingIntent2);
- if (samePackage(packageName1, packageName2, userId1, userId2)) {
- if (mMultiInstanceHelpher.supportsMultiInstanceSplit(getComponent(pendingIntent1))) {
- fillInIntent1 = new Intent();
- fillInIntent1.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
- fillInIntent2 = new Intent();
- fillInIntent2.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
- } else {
- pendingIntent2 = null;
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
- "Cancel entering split as not supporting multi-instances");
- Log.w(TAG, splitFailureMessage("startIntentsWithLegacyTransition",
- "app package " + packageName1 + " does not support multi-instance"));
- Toast.makeText(mContext, R.string.dock_multi_instances_not_supported_text,
- Toast.LENGTH_SHORT).show();
- }
- }
- mStageCoordinator.startIntentsWithLegacyTransition(pendingIntent1, fillInIntent1,
- shortcutInfo1, options1, pendingIntent2, fillInIntent2, shortcutInfo2, options2,
- splitPosition, snapPosition, adapter, instanceId);
- }
-
private void startIntents(PendingIntent pendingIntent1, int userId1,
@Nullable ShortcutInfo shortcutInfo1, @Nullable Bundle options1,
PendingIntent pendingIntent2, int userId2, @Nullable ShortcutInfo shortcutInfo2,
@@ -876,11 +794,8 @@
if (taskInfo != null) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
"Found suitable background task=%s", taskInfo);
- if (ENABLE_SHELL_TRANSITIONS) {
- mStageCoordinator.startTask(taskInfo.taskId, position, options, hideTaskToken);
- } else {
- startTask(taskInfo.taskId, position, options, hideTaskToken);
- }
+ mStageCoordinator.startTask(taskInfo.taskId, position, options, hideTaskToken);
+
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Start task in background");
return;
}
@@ -980,63 +895,6 @@
return fillInIntent2;
}
- RemoteAnimationTarget[] onGoingToRecentsLegacy(RemoteAnimationTarget[] apps) {
- if (ENABLE_SHELL_TRANSITIONS) return null;
-
- if (isSplitScreenVisible()) {
- // Evict child tasks except the top visible one under split root to ensure it could be
- // launched as full screen when switching to it on recents.
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- mStageCoordinator.prepareEvictInvisibleChildTasks(wct);
- mSyncQueue.queue(wct);
- } else {
- return null;
- }
-
- SurfaceControl.Transaction t = mTransactionPool.acquire();
- if (mGoingToRecentsTasksLayer != null) {
- t.remove(mGoingToRecentsTasksLayer);
- }
- mGoingToRecentsTasksLayer = reparentSplitTasksForAnimation(apps, t,
- "SplitScreenController#onGoingToRecentsLegacy" /* callsite */);
- t.apply();
- mTransactionPool.release(t);
-
- return new RemoteAnimationTarget[]{mStageCoordinator.getDividerBarLegacyTarget()};
- }
-
- RemoteAnimationTarget[] onStartingSplitLegacy(RemoteAnimationTarget[] apps) {
- if (ENABLE_SHELL_TRANSITIONS) return null;
-
- int openingApps = 0;
- for (int i = 0; i < apps.length; ++i) {
- if (apps[i].mode == MODE_OPENING) openingApps++;
- }
- if (openingApps < 2) {
- // Not having enough apps to enter split screen
- return null;
- }
-
- SurfaceControl.Transaction t = mTransactionPool.acquire();
- if (mStartingSplitTasksLayer != null) {
- t.remove(mStartingSplitTasksLayer);
- }
- mStartingSplitTasksLayer = reparentSplitTasksForAnimation(apps, t,
- "SplitScreenController#onStartingSplitLegacy" /* callsite */);
- t.apply();
- mTransactionPool.release(t);
-
- try {
- return new RemoteAnimationTarget[]{mStageCoordinator.getDividerBarLegacyTarget()};
- } finally {
- for (RemoteAnimationTarget appTarget : apps) {
- if (appTarget.leash != null) {
- appTarget.leash.release();
- }
- }
- }
- }
-
private SurfaceControl reparentSplitTasksForAnimation(RemoteAnimationTarget[] apps,
SurfaceControl.Transaction t, String callsite) {
final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
@@ -1333,41 +1191,6 @@
}
@Override
- public void startTasksWithLegacyTransition(int taskId1, @Nullable Bundle options1,
- int taskId2, @Nullable Bundle options2, @SplitPosition int splitPosition,
- @PersistentSnapPosition int snapPosition, RemoteAnimationAdapter adapter,
- InstanceId instanceId) {
- executeRemoteCallWithTaskPermission(mController, "startTasks",
- (controller) -> controller.mStageCoordinator.startTasksWithLegacyTransition(
- taskId1, options1, taskId2, options2, splitPosition, snapPosition,
- adapter, instanceId));
- }
-
- @Override
- public void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent, int userId1,
- Bundle options1, int taskId, Bundle options2, int splitPosition,
- @PersistentSnapPosition int snapPosition, RemoteAnimationAdapter adapter,
- InstanceId instanceId) {
- executeRemoteCallWithTaskPermission(mController,
- "startIntentAndTaskWithLegacyTransition", (controller) ->
- controller.startIntentAndTaskWithLegacyTransition(pendingIntent,
- userId1, options1, taskId, options2, splitPosition,
- snapPosition, adapter, instanceId));
- }
-
- @Override
- public void startShortcutAndTaskWithLegacyTransition(ShortcutInfo shortcutInfo,
- @Nullable Bundle options1, int taskId, @Nullable Bundle options2,
- @SplitPosition int splitPosition, @PersistentSnapPosition int snapPosition,
- RemoteAnimationAdapter adapter, InstanceId instanceId) {
- executeRemoteCallWithTaskPermission(mController,
- "startShortcutAndTaskWithLegacyTransition", (controller) ->
- controller.startShortcutAndTaskWithLegacyTransition(
- shortcutInfo, options1, taskId, options2, splitPosition,
- snapPosition, adapter, instanceId));
- }
-
- @Override
public void startTasks(int taskId1, @Nullable Bundle options1, int taskId2,
@Nullable Bundle options2, @SplitPosition int splitPosition,
@PersistentSnapPosition int snapPosition,
@@ -1400,21 +1223,6 @@
}
@Override
- public void startIntentsWithLegacyTransition(PendingIntent pendingIntent1, int userId1,
- @Nullable ShortcutInfo shortcutInfo1, @Nullable Bundle options1,
- PendingIntent pendingIntent2, int userId2, @Nullable ShortcutInfo shortcutInfo2,
- @Nullable Bundle options2, @SplitPosition int splitPosition,
- @PersistentSnapPosition int snapPosition, RemoteAnimationAdapter adapter,
- InstanceId instanceId) {
- executeRemoteCallWithTaskPermission(mController, "startIntentsWithLegacyTransition",
- (controller) ->
- controller.startIntentsWithLegacyTransition(pendingIntent1, userId1,
- shortcutInfo1, options1, pendingIntent2, userId2, shortcutInfo2,
- options2, splitPosition, snapPosition, adapter, instanceId)
- );
- }
-
- @Override
public void startIntents(PendingIntent pendingIntent1, int userId1,
@Nullable ShortcutInfo shortcutInfo1, @Nullable Bundle options1,
PendingIntent pendingIntent2, int userId2, @Nullable ShortcutInfo shortcutInfo2,
@@ -1446,24 +1254,6 @@
}
@Override
- public RemoteAnimationTarget[] onGoingToRecentsLegacy(RemoteAnimationTarget[] apps) {
- final RemoteAnimationTarget[][] out = new RemoteAnimationTarget[][]{null};
- executeRemoteCallWithTaskPermission(mController, "onGoingToRecentsLegacy",
- (controller) -> out[0] = controller.onGoingToRecentsLegacy(apps),
- true /* blocking */);
- return out[0];
- }
-
- @Override
- public RemoteAnimationTarget[] onStartingSplitLegacy(RemoteAnimationTarget[] apps) {
- final RemoteAnimationTarget[][] out = new RemoteAnimationTarget[][]{null};
- executeRemoteCallWithTaskPermission(mController, "onStartingSplitLegacy",
- (controller) -> out[0] = controller.onStartingSplitLegacy(apps),
- true /* blocking */);
- return out[0];
- }
-
- @Override
public void switchSplitPosition() {
executeRemoteCallWithTaskPermission(mController, "switchSplitPosition",
(controller) -> controller.switchSplitPosition("remoteCall"));
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 2531ff1..a7551bd 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
@@ -24,8 +24,6 @@
import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
import static android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.RemoteAnimationTarget.MODE_OPENING;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
@@ -59,14 +57,12 @@
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DRAG_DIVIDER;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_FULLSCREEN_REQUEST;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_FULLSCREEN_SHORTCUT;
-import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RECREATE_SPLIT;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_ROOT_TASK_VANISHED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_UNKNOWN;
import static com.android.wm.shell.splitscreen.SplitScreenController.exitReasonToString;
import static com.android.wm.shell.transition.MixedTransitionHelper.getPipReplacingChange;
-import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE;
import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_SCREEN_PAIR_OPEN;
@@ -81,7 +77,6 @@
import android.app.IActivityTaskManager;
import android.app.PendingIntent;
import android.app.TaskInfo;
-import android.app.WindowConfiguration;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
@@ -121,7 +116,6 @@
import com.android.internal.logging.InstanceId;
import com.android.internal.policy.FoldLockSettingsObserver;
import com.android.internal.protolog.ProtoLog;
-import com.android.internal.util.ArrayUtils;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -143,9 +137,7 @@
import com.android.wm.shell.shared.TransitionUtil;
import com.android.wm.shell.splitscreen.SplitScreen.StageType;
import com.android.wm.shell.splitscreen.SplitScreenController.ExitReason;
-import com.android.wm.shell.splitscreen.SplitScreenController.SplitEnterReason;
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;
import com.android.wm.shell.windowdecor.WindowDecorViewModel;
@@ -227,7 +219,7 @@
// Tracks whether we should update the recent tasks. Only allow this to happen in between enter
// and exit, since exit itself can trigger a number of changes that update the stages.
- private boolean mShouldUpdateRecents;
+ private boolean mShouldUpdateRecents = true;
private boolean mExitSplitScreenOnHide;
private boolean mIsDividerRemoteAnimating;
private boolean mIsDropEntering;
@@ -368,11 +360,7 @@
transitions.addHandler(this);
mSplitUnsupportedToast = Toast.makeText(mContext,
R.string.dock_non_resizeble_failed_to_dock_text, Toast.LENGTH_SHORT);
- // With shell transition, we should update recents tile each callback so set this to true by
- // default.
- mShouldUpdateRecents = ENABLE_SHELL_TRANSITIONS;
- mFoldLockSettingsObserver =
- new FoldLockSettingsObserver(mainHandler, context);
+ mFoldLockSettingsObserver = new FoldLockSettingsObserver(mainHandler, context);
mFoldLockSettingsObserver.register();
}
@@ -491,18 +479,12 @@
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "moveToStage: task=%d position=%d", task.taskId,
stagePosition);
prepareEnterSplitScreen(wct, task, stagePosition, false /* resizeAnim */);
- if (ENABLE_SHELL_TRANSITIONS) {
- mSplitTransitions.startEnterTransition(TRANSIT_TO_FRONT, wct,
- null, this,
- isSplitScreenVisible()
- ? TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE : TRANSIT_SPLIT_SCREEN_PAIR_OPEN,
- !mIsDropEntering);
- } else {
- mSyncQueue.queue(wct);
- mSyncQueue.runInSync(t -> {
- updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */);
- });
- }
+ mSplitTransitions.startEnterTransition(TRANSIT_TO_FRONT, wct,
+ null, this,
+ isSplitScreenVisible()
+ ? TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE : TRANSIT_SPLIT_SCREEN_PAIR_OPEN,
+ !mIsDropEntering);
+
// Due to drag already pip task entering split by this method so need to reset flag here.
mIsDropEntering = false;
mSkipEvictingMainStageChildren = false;
@@ -653,10 +635,6 @@
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "startIntent: intent=%s position=%d", intent.getIntent(),
position);
mSplitRequest = new SplitRequest(intent.getIntent(), position);
- if (!ENABLE_SHELL_TRANSITIONS) {
- startIntentLegacy(intent, fillInIntent, position, options);
- return;
- }
final WindowContainerTransaction wct = new WindowContainerTransaction();
options = resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, null /* wct */);
@@ -690,63 +668,6 @@
extraTransitType, !mIsDropEntering);
}
- /** Launches an activity into split by legacy transition. */
- void startIntentLegacy(PendingIntent intent, Intent fillInIntent, @SplitPosition int position,
- @Nullable Bundle options) {
- final boolean isEnteringSplit = !isSplitActive();
-
- LegacyTransitions.ILegacyTransition transition = new LegacyTransitions.ILegacyTransition() {
- @Override
- public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
- RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
- IRemoteAnimationFinishedCallback finishedCallback,
- SurfaceControl.Transaction t) {
- if (isEnteringSplit && mSideStage.getChildCount() == 0) {
- mMainExecutor.execute(() -> exitSplitScreen(
- null /* childrenToTop */, EXIT_REASON_UNKNOWN));
- Log.w(TAG, splitFailureMessage("startIntentLegacy",
- "side stage was not populated"));
- handleUnsupportedSplitStart();
- }
-
- if (apps != null) {
- for (int i = 0; i < apps.length; ++i) {
- if (apps[i].mode == MODE_OPENING) {
- t.show(apps[i].leash);
- }
- }
- }
- t.apply();
-
- if (finishedCallback != null) {
- try {
- finishedCallback.onAnimationFinished();
- } catch (RemoteException e) {
- Slog.e(TAG, "Error finishing legacy transition: ", e);
- }
- }
-
-
- if (!isEnteringSplit && apps != null) {
- final WindowContainerTransaction evictWct = new WindowContainerTransaction();
- prepareEvictNonOpeningChildTasks(position, apps, evictWct);
- mSyncQueue.queue(evictWct);
- }
- }
- };
-
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- options = resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, wct);
-
- // If split still not active, apply windows bounds first to avoid surface reset to
- // wrong pos by SurfaceAnimator from wms.
- if (isEnteringSplit && mLogger.isEnterRequestedByDrag()) {
- updateWindowBounds(mSplitLayout, wct);
- }
- wct.sendPendingIntent(intent, fillInIntent, options);
- mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct);
- }
-
/** Starts 2 tasks in one transition. */
void startTasks(int taskId1, @Nullable Bundle options1, int taskId2, @Nullable Bundle options2,
@SplitPosition int splitPosition, @PersistentSnapPosition int snapPosition,
@@ -991,373 +912,12 @@
mSplitTransitions.startFullscreenTransition(wct, remoteTransition);
}
- /** Starts a pair of tasks using legacy transition. */
- void startTasksWithLegacyTransition(int taskId1, @Nullable Bundle options1,
- int taskId2, @Nullable Bundle options2, @SplitPosition int splitPosition,
- @PersistentSnapPosition int snapPosition, RemoteAnimationAdapter adapter,
- InstanceId instanceId) {
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- if (options1 == null) options1 = new Bundle();
- if (taskId2 == INVALID_TASK_ID) {
- // Launching a solo task.
- // Exit split first if this task under split roots.
- if (mMainStage.containsTask(taskId1) || mSideStage.containsTask(taskId1)) {
- exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RECREATE_SPLIT);
- }
- ActivityOptions activityOptions = ActivityOptions.fromBundle(options1);
- activityOptions.update(ActivityOptions.makeRemoteAnimation(adapter));
- options1 = activityOptions.toBundle();
- addActivityOptions(options1, null /* launchTarget */);
- wct.startTask(taskId1, options1);
- mSyncQueue.queue(wct);
- return;
- }
-
- addActivityOptions(options1, mSideStage);
- wct.startTask(taskId1, options1);
- mSplitRequest = new SplitRequest(taskId1, taskId2, splitPosition);
- startWithLegacyTransition(wct, taskId2, options2, splitPosition, snapPosition, adapter,
- instanceId);
- }
-
- /** Starts a pair of intents using legacy transition. */
- void startIntentsWithLegacyTransition(PendingIntent pendingIntent1, Intent fillInIntent1,
- @Nullable ShortcutInfo shortcutInfo1, @Nullable Bundle options1,
- @Nullable PendingIntent pendingIntent2, Intent fillInIntent2,
- @Nullable ShortcutInfo shortcutInfo2, @Nullable Bundle options2,
- @SplitPosition int splitPosition, @PersistentSnapPosition int snapPosition,
- RemoteAnimationAdapter adapter, InstanceId instanceId) {
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- if (options1 == null) options1 = new Bundle();
- if (pendingIntent2 == null) {
- // Launching a solo intent or shortcut as fullscreen.
- launchAsFullscreenWithRemoteAnimation(pendingIntent1, fillInIntent1, shortcutInfo1,
- options1, adapter, wct);
- return;
- }
-
- addActivityOptions(options1, mSideStage);
- if (shortcutInfo1 != null) {
- wct.startShortcut(mContext.getPackageName(), shortcutInfo1, options1);
- } else {
- wct.sendPendingIntent(pendingIntent1, fillInIntent1, options1);
- mSplitRequest = new SplitRequest(pendingIntent1.getIntent(),
- pendingIntent2 != null ? pendingIntent2.getIntent() : null, splitPosition);
- }
- startWithLegacyTransition(wct, pendingIntent2, fillInIntent2, shortcutInfo2, options2,
- splitPosition, snapPosition, adapter, instanceId);
- }
-
- void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent, Intent fillInIntent,
- @Nullable Bundle options1, int taskId, @Nullable Bundle options2,
- @SplitPosition int splitPosition, @PersistentSnapPosition int snapPosition,
- RemoteAnimationAdapter adapter, InstanceId instanceId) {
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- if (options1 == null) options1 = new Bundle();
- if (taskId == INVALID_TASK_ID) {
- // Launching a solo intent as fullscreen.
- launchAsFullscreenWithRemoteAnimation(pendingIntent, fillInIntent, null, options1,
- adapter, wct);
- return;
- }
-
- addActivityOptions(options1, mSideStage);
- wct.sendPendingIntent(pendingIntent, fillInIntent, options1);
- mSplitRequest = new SplitRequest(taskId, pendingIntent.getIntent(), splitPosition);
- startWithLegacyTransition(wct, taskId, options2, splitPosition, snapPosition, adapter,
- instanceId);
- }
-
- /** Starts a pair of shortcut and task using legacy transition. */
- void startShortcutAndTaskWithLegacyTransition(ShortcutInfo shortcutInfo,
- @Nullable Bundle options1, int taskId, @Nullable Bundle options2,
- @SplitPosition int splitPosition, @PersistentSnapPosition int snapPosition,
- RemoteAnimationAdapter adapter, InstanceId instanceId) {
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- if (options1 == null) options1 = new Bundle();
- if (taskId == INVALID_TASK_ID) {
- // Launching a solo shortcut as fullscreen.
- launchAsFullscreenWithRemoteAnimation(null, null, shortcutInfo, options1, adapter, wct);
- return;
- }
-
- addActivityOptions(options1, mSideStage);
- wct.startShortcut(mContext.getPackageName(), shortcutInfo, options1);
- startWithLegacyTransition(wct, taskId, options2, splitPosition, snapPosition, adapter,
- instanceId);
- }
-
- private void launchAsFullscreenWithRemoteAnimation(@Nullable PendingIntent pendingIntent,
- @Nullable Intent fillInIntent, @Nullable ShortcutInfo shortcutInfo,
- @Nullable Bundle options, RemoteAnimationAdapter adapter,
- WindowContainerTransaction wct) {
- LegacyTransitions.ILegacyTransition transition =
- (transit, apps, wallpapers, nonApps, finishedCallback, t) -> {
- if (apps == null || apps.length == 0) {
- onRemoteAnimationFinished(apps);
- t.apply();
- try {
- adapter.getRunner().onAnimationCancelled();
- } catch (RemoteException e) {
- Slog.e(TAG, "Error starting remote animation", e);
- }
- return;
- }
-
- for (int i = 0; i < apps.length; ++i) {
- if (apps[i].mode == MODE_OPENING) {
- t.show(apps[i].leash);
- }
- }
- t.apply();
-
- try {
- adapter.getRunner().onAnimationStart(
- transit, apps, wallpapers, nonApps, finishedCallback);
- } catch (RemoteException e) {
- Slog.e(TAG, "Error starting remote animation", e);
- }
- };
-
- addActivityOptions(options, null /* launchTarget */);
- if (shortcutInfo != null) {
- wct.startShortcut(mContext.getPackageName(), shortcutInfo, options);
- } else if (pendingIntent != null) {
- wct.sendPendingIntent(pendingIntent, fillInIntent, options);
- } else {
- Slog.e(TAG, "Pending intent and shortcut are null is invalid case.");
- }
- mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct);
- }
-
- private void startWithLegacyTransition(WindowContainerTransaction wct,
- @Nullable PendingIntent mainPendingIntent, @Nullable Intent mainFillInIntent,
- @Nullable ShortcutInfo mainShortcutInfo, @Nullable Bundle mainOptions,
- @SplitPosition int sidePosition, @PersistentSnapPosition int snapPosition,
- RemoteAnimationAdapter adapter, InstanceId instanceId) {
- startWithLegacyTransition(wct, INVALID_TASK_ID, mainPendingIntent, mainFillInIntent,
- mainShortcutInfo, mainOptions, sidePosition, snapPosition, adapter, instanceId);
- }
-
- private void startWithLegacyTransition(WindowContainerTransaction wct, int mainTaskId,
- @Nullable Bundle mainOptions, @SplitPosition int sidePosition,
- @PersistentSnapPosition int snapPosition, RemoteAnimationAdapter adapter,
- InstanceId instanceId) {
- startWithLegacyTransition(wct, mainTaskId, null /* mainPendingIntent */,
- null /* mainFillInIntent */, null /* mainShortcutInfo */, mainOptions, sidePosition,
- snapPosition, adapter, instanceId);
- }
-
- /**
- * @param wct transaction to start the first task
- * @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 PendingIntent mainPendingIntent, @Nullable Intent mainFillInIntent,
- @Nullable ShortcutInfo mainShortcutInfo, @Nullable Bundle options,
- @SplitPosition int sidePosition, @PersistentSnapPosition int snapPosition,
- RemoteAnimationAdapter adapter, InstanceId instanceId) {
- if (!isSplitScreenVisible()) {
- exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RECREATE_SPLIT);
- }
-
- // Init divider first to make divider leash for remote animation target.
- mSplitLayout.init();
- mSplitLayout.setDivideRatio(snapPosition);
-
- // Apply surface bounds before animation start.
- SurfaceControl.Transaction startT = mTransactionPool.acquire();
- updateSurfaceBounds(mSplitLayout, startT, false /* applyResizingOffset */);
- startT.apply();
- mTransactionPool.release(startT);
-
- // Set false to avoid record new bounds with old task still on top;
- mShouldUpdateRecents = false;
- mIsDividerRemoteAnimating = true;
- if (mSplitRequest == null) {
- mSplitRequest = new SplitRequest(mainTaskId,
- mainPendingIntent != null ? mainPendingIntent.getIntent() : null,
- sidePosition);
- }
- setSideStagePosition(sidePosition, wct);
- if (!mMainStage.isActive()) {
- mMainStage.activate(wct, false /* reparent */);
- }
-
- if (options == null) options = new Bundle();
- addActivityOptions(options, mMainStage);
-
- updateWindowBounds(mSplitLayout, wct);
- wct.reorder(mRootTaskInfo.token, true);
- setRootForceTranslucent(false, wct);
-
- // TODO(b/268008375): Merge APIs to start a split pair into one.
- if (mainTaskId != INVALID_TASK_ID) {
- options = wrapAsSplitRemoteAnimation(adapter, options);
- wct.startTask(mainTaskId, options);
- mSyncQueue.queue(wct);
- } else {
- if (mainShortcutInfo != null) {
- wct.startShortcut(mContext.getPackageName(), mainShortcutInfo, options);
- } else {
- wct.sendPendingIntent(mainPendingIntent, mainFillInIntent, options);
- }
- mSyncQueue.queue(wrapAsSplitRemoteAnimation(adapter), WindowManager.TRANSIT_OPEN, wct);
- }
-
- setEnterInstanceId(instanceId);
- }
-
- private Bundle wrapAsSplitRemoteAnimation(RemoteAnimationAdapter adapter, Bundle options) {
- final WindowContainerTransaction evictWct = new WindowContainerTransaction();
- if (isSplitScreenVisible()) {
- mMainStage.evictAllChildren(evictWct);
- mSideStage.evictAllChildren(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 {
- onRemoteAnimationFinishedOrCancelled(evictWct);
- finishedCallback.onAnimationFinished();
- }
- };
- Transitions.setRunningRemoteTransitionDelegate(adapter.getCallingApplication());
- try {
- 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() {
- onRemoteAnimationFinishedOrCancelled(evictWct);
- setDividerVisibility(true, null);
- try {
- adapter.getRunner().onAnimationCancelled();
- } catch (RemoteException e) {
- Slog.e(TAG, "Error starting remote animation", e);
- }
- }
- };
- RemoteAnimationAdapter wrappedAdapter = new RemoteAnimationAdapter(
- wrapper, adapter.getDuration(), adapter.getStatusBarTransitionDelay());
- ActivityOptions activityOptions = ActivityOptions.fromBundle(options);
- activityOptions.update(ActivityOptions.makeRemoteAnimation(wrappedAdapter));
- return activityOptions.toBundle();
- }
-
- private LegacyTransitions.ILegacyTransition wrapAsSplitRemoteAnimation(
- RemoteAnimationAdapter adapter) {
- LegacyTransitions.ILegacyTransition transition =
- (transit, apps, wallpapers, nonApps, finishedCallback, t) -> {
- if (apps == null || apps.length == 0) {
- onRemoteAnimationFinished(apps);
- t.apply();
- try {
- adapter.getRunner().onAnimationCancelled();
- } 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());
-
- 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 offset.
- t.setPosition(apps[i].leash, 0, 0);
- }
- }
- setDividerVisibility(true, t);
- t.apply();
-
- IRemoteAnimationFinishedCallback wrapCallback =
- new IRemoteAnimationFinishedCallback.Stub() {
- @Override
- public void onAnimationFinished() throws RemoteException {
- onRemoteAnimationFinished(apps);
- finishedCallback.onAnimationFinished();
- }
- };
- Transitions.setRunningRemoteTransitionDelegate(adapter.getCallingApplication());
- try {
- adapter.getRunner().onAnimationStart(
- transit, apps, wallpapers, nonApps, wrapCallback);
- } catch (RemoteException e) {
- Slog.e(TAG, "Error starting remote animation", e);
- }
- };
-
- return transition;
- }
-
private void setEnterInstanceId(InstanceId instanceId) {
if (instanceId != null) {
mLogger.enterRequested(instanceId, ENTER_REASON_LAUNCHER);
}
}
- private void onRemoteAnimationFinishedOrCancelled(WindowContainerTransaction evictWct) {
- mIsDividerRemoteAnimating = false;
- mShouldUpdateRecents = true;
- clearRequestIfPresented();
- // 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 (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) {
- mMainExecutor.execute(() ->
- exitSplitScreen(mMainStage.getChildCount() == 0
- ? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
- Log.w(TAG, splitFailureMessage("onRemoteAnimationFinishedOrCancelled",
- "main or side stage was not populated."));
- handleUnsupportedSplitStart();
- } else {
- mSyncQueue.queue(evictWct);
- mSyncQueue.runInSync(t -> {
- updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */);
- });
- }
- }
-
- private void onRemoteAnimationFinished(RemoteAnimationTarget[] apps) {
- mIsDividerRemoteAnimating = false;
- mShouldUpdateRecents = true;
- clearRequestIfPresented();
- // 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));
- Log.w(TAG, splitFailureMessage("onRemoteAnimationFinished",
- "main or side stage was not populated"));
- handleUnsupportedSplitStart();
- return;
- }
-
- final WindowContainerTransaction evictWct = new WindowContainerTransaction();
- mMainStage.evictNonOpeningChildren(apps, evictWct);
- mSideStage.evictNonOpeningChildren(apps, evictWct);
- mSyncQueue.queue(evictWct);
- }
-
void prepareEvictNonOpeningChildTasks(@SplitPosition int position, RemoteAnimationTarget[] apps,
WindowContainerTransaction wct) {
if (position == mSideStagePosition) {
@@ -1576,18 +1136,13 @@
return;
}
- if (ENABLE_SHELL_TRANSITIONS) {
- // Need manually clear here due to this transition might be aborted due to keyguard
- // on top and lead to no visible change.
- clearSplitPairedInRecents(reason);
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- prepareExitSplitScreen(mLastActiveStage, wct);
- mSplitTransitions.startDismissTransition(wct, this, mLastActiveStage, reason);
- setSplitsVisible(false);
- } else {
- exitSplitScreen(mLastActiveStage == STAGE_TYPE_MAIN ? mMainStage : mSideStage, reason);
- }
-
+ // Need manually clear here due to this transition might be aborted due to keyguard
+ // on top and lead to no visible change.
+ clearSplitPairedInRecents(reason);
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ prepareExitSplitScreen(mLastActiveStage, wct);
+ mSplitTransitions.startDismissTransition(wct, this, mLastActiveStage, reason);
+ setSplitsVisible(false);
mBreakOnNextWake = false;
}
@@ -1596,26 +1151,6 @@
}
/** Exits split screen with legacy transition */
- void exitSplitScreen(int toTopTaskId, @ExitReason int exitReason) {
- ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "exitSplitScreen: topTaskId=%d reason=%s active=%b",
- toTopTaskId, exitReasonToString(exitReason), mMainStage.isActive());
- if (!mMainStage.isActive()) return;
-
- StageTaskListener childrenToTop = null;
- if (mMainStage.containsTask(toTopTaskId)) {
- childrenToTop = mMainStage;
- } else if (mSideStage.containsTask(toTopTaskId)) {
- childrenToTop = mSideStage;
- }
-
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- if (childrenToTop != null) {
- childrenToTop.reorderChild(toTopTaskId, true /* onTop */, wct);
- }
- applyExitSplitScreen(childrenToTop, wct, exitReason);
- }
-
- /** Exits split screen with legacy transition */
private void exitSplitScreen(@Nullable StageTaskListener childrenToTop,
@ExitReason int exitReason) {
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "exitSplitScreen: mainStageToTop=%b reason=%s active=%b",
@@ -1865,15 +1400,9 @@
boolean resizeAnim) {
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "prepareActiveSplit: task=%d isSplitVisible=%b",
taskInfo != null ? taskInfo.taskId : -1, isSplitScreenVisible());
- if (!ENABLE_SHELL_TRANSITIONS) {
- // Legacy transition we need to create divider here, shell transition case we will
- // create it on #finishEnterSplitScreen
- mSplitLayout.init();
- } else {
- // We handle split visibility itself on shell transition, but sometimes we didn't
- // reset it correctly after dismiss by some reason, so just set invisible before active.
- setSplitsVisible(false);
- }
+ // We handle split visibility itself on shell transition, but sometimes we didn't
+ // reset it correctly after dismiss by some reason, so just set invisible before active.
+ setSplitsVisible(false);
if (taskInfo != null) {
setSideStagePosition(startPosition, wct);
mSideStage.addTask(taskInfo, wct);
@@ -2420,10 +1949,6 @@
bottomOrRight ? mSideStagePosition == SPLIT_POSITION_BOTTOM_OR_RIGHT
: mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT;
final StageTaskListener toTopStage = mainStageToTop ? mMainStage : mSideStage;
- if (!ENABLE_SHELL_TRANSITIONS) {
- exitSplitScreen(toTopStage, exitReason);
- return;
- }
final int dismissTop = mainStageToTop ? STAGE_TYPE_MAIN : STAGE_TYPE_SIDE;
final WindowContainerTransaction wct = new WindowContainerTransaction();
@@ -2481,28 +2006,13 @@
}
sendOnBoundsChanged();
- if (ENABLE_SHELL_TRANSITIONS) {
- mSplitLayout.setDividerInteractive(false, false, "onSplitResizeStart");
- mSplitTransitions.startResizeTransition(wct, this, (aborted) -> {
- mSplitLayout.setDividerInteractive(true, false, "onSplitResizeConsumed");
- }, (finishWct, t) -> {
- mSplitLayout.setDividerInteractive(true, false, "onSplitResizeFinish");
- }, mMainStage.getSplitDecorManager(), mSideStage.getSplitDecorManager());
- } else {
- // Only need screenshot for legacy case because shell transition should screenshot
- // itself during transition.
- final SurfaceControl.Transaction startT = mTransactionPool.acquire();
- mMainStage.screenshotIfNeeded(startT);
- mSideStage.screenshotIfNeeded(startT);
- mTransactionPool.release(startT);
+ mSplitLayout.setDividerInteractive(false, false, "onSplitResizeStart");
+ mSplitTransitions.startResizeTransition(wct, this, (aborted) -> {
+ mSplitLayout.setDividerInteractive(true, false, "onSplitResizeConsumed");
+ }, (finishWct, t) -> {
+ mSplitLayout.setDividerInteractive(true, false, "onSplitResizeFinish");
+ }, mMainStage.getSplitDecorManager(), mSideStage.getSplitDecorManager());
- mSyncQueue.queue(wct);
- mSyncQueue.runInSync(t -> {
- updateSurfaceBounds(layout, t, false /* applyResizingOffset */);
- mMainStage.onResized(t);
- mSideStage.onResized(t);
- });
- }
mLogger.logResize(mSplitLayout.getDividerPositionAsFraction());
}
@@ -3603,16 +3113,6 @@
info.addChange(barChange);
}
- RemoteAnimationTarget getDividerBarLegacyTarget() {
- final Rect bounds = mSplitLayout.getDividerBounds();
- return new RemoteAnimationTarget(-1 /* taskId */, -1 /* mode */,
- mSplitLayout.getDividerLeash(), false /* isTranslucent */, null /* clipRect */,
- null /* contentInsets */, Integer.MAX_VALUE /* prefixOrderIndex */,
- new android.graphics.Point(0, 0) /* position */, bounds, bounds,
- new WindowConfiguration(), true, null /* startLeash */, null /* startBounds */,
- null /* taskInfo */, false /* allowEnterPip */, TYPE_DOCK_DIVIDER);
- }
-
@NeverCompile
@Override
public void dump(@NonNull PrintWriter pw, String prefix) {
@@ -3663,30 +3163,10 @@
mIsDropEntering = true;
mSkipEvictingMainStageChildren = true;
}
- if (!isSplitScreenVisible() && !ENABLE_SHELL_TRANSITIONS) {
- // If split running background, exit split first.
- // Skip this on shell transition due to we could evict existing tasks on transition
- // finished.
- exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RECREATE_SPLIT);
- }
mLogger.enterRequestedByDrag(position, dragSessionId);
}
/**
- * Sets info to be logged when splitscreen is next entered.
- */
- public void onRequestToSplit(InstanceId sessionId, @SplitEnterReason int enterReason) {
- ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onRequestToSplit: reason=%d", enterReason);
- if (!isSplitScreenVisible() && !ENABLE_SHELL_TRANSITIONS) {
- // If split running background, exit split first.
- // Skip this on shell transition due to we could evict existing tasks on transition
- // finished.
- exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RECREATE_SPLIT);
- }
- mLogger.enterRequested(sessionId, enterReason);
- }
-
- /**
* Logs the exit of splitscreen.
*/
private void logExit(@ExitReason int exitReason) {
@@ -3768,12 +3248,6 @@
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onNoLongerSupportMultiWindow: task=%s", taskInfo);
if (mMainStage.isActive()) {
final boolean isMainStage = mMainStageListener == this;
- if (!ENABLE_SHELL_TRANSITIONS) {
- StageCoordinator.this.exitSplitScreen(isMainStage ? mMainStage : mSideStage,
- EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW);
- handleUnsupportedSplitStart();
- return;
- }
// If visible, we preserve the app and keep it running. If an app becomes
// unsupported in the bg, break split without putting anything on top
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
index 90eb22f..759f97f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -17,6 +17,7 @@
package com.android.wm.shell.startingsurface;
import static android.content.Context.CONTEXT_RESTRICTED;
+import static android.content.res.Configuration.UI_MODE_NIGHT_MASK;
import static android.os.Process.THREAD_PRIORITY_TOP_APP_BOOST;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -191,31 +192,15 @@
}
final Configuration taskConfig = taskInfo.getConfiguration();
- if (taskConfig.diffPublicOnly(context.getResources().getConfiguration()) != 0) {
+ final Configuration contextConfig = context.getResources().getConfiguration();
+ if ((taskConfig.uiMode & UI_MODE_NIGHT_MASK)
+ != (contextConfig.uiMode & UI_MODE_NIGHT_MASK)) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
"addSplashScreen: creating context based on task Configuration %s",
taskConfig);
final Context overrideContext = context.createConfigurationContext(taskConfig);
overrideContext.setTheme(theme);
- final TypedArray typedArray = overrideContext.obtainStyledAttributes(
- com.android.internal.R.styleable.Window);
- final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
- try {
- if (resId != 0 && overrideContext.getDrawable(resId) != null) {
- // We want to use the windowBackground for the override context if it is
- // available, otherwise we use the default one to make sure a themed starting
- // window is displayed for the app.
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
- "addSplashScreen: apply overrideConfig %s",
- taskConfig);
- context = overrideContext;
- }
- } catch (Resources.NotFoundException e) {
- Slog.w(TAG, "failed creating starting window for overrideConfig at taskId: "
- + taskId, e);
- return null;
- }
- typedArray.recycle();
+ context = overrideContext;
}
return context;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
index e6d1b45..15fe7ab 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
@@ -217,6 +217,11 @@
return null;
}
+ /** Returns true if the given {@code taskInfo} belongs to a task view. */
+ public boolean isTaskViewTask(ActivityManager.RunningTaskInfo taskInfo) {
+ return findTaskView(taskInfo) != null;
+ }
+
void startTaskView(@NonNull WindowContainerTransaction wct,
@NonNull TaskViewTaskController taskView, @NonNull IBinder launchCookie) {
updateVisibilityState(taskView, true /* visible */);
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 d8c8c60..7784784 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
@@ -502,8 +502,7 @@
backgroundColorForTransition = getTransitionBackgroundColorIfSet(info, change, a,
backgroundColorForTransition);
- if (!com.android.graphics.libgui.flags.Flags.edgeExtensionShader() && !isTask
- && a.getExtensionEdges() != 0) {
+ if (!isTask && a.hasExtension()) {
if (!TransitionUtil.isOpeningType(mode)) {
// Can screenshot now (before startTransaction is applied)
edgeExtendWindow(change, a, startTransaction, finishTransaction);
@@ -513,8 +512,6 @@
postStartTransactionCallbacks
.add(t -> edgeExtendWindow(change, a, t, finishTransaction));
}
- } else if (com.android.graphics.libgui.flags.Flags.edgeExtensionShader()) {
- finishTransaction.setEdgeExtensionEffect(change.getLeash(), /* edge */ 0);
}
final Rect clipRect = TransitionUtil.isClosingType(mode)
@@ -1011,10 +1008,6 @@
Point position, float cornerRadius, @Nullable Rect immutableClipRect) {
tmpTransformation.clear();
anim.getTransformation(time, tmpTransformation);
- if (anim.getExtensionEdges() != 0
- && com.android.graphics.libgui.flags.Flags.edgeExtensionShader()) {
- t.setEdgeExtensionEffect(leash, anim.getExtensionEdges());
- }
if (position != null) {
tmpTransformation.getMatrix().postTranslate(position.x, position.y);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 874cca5..c850ff8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -38,9 +38,9 @@
import static android.window.TransitionInfo.FLAG_NO_ANIMATION;
import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
-import static com.android.window.flags.Flags.enforceShellThreadModel;
import static com.android.window.flags.Flags.ensureWallpaperInTransitions;
import static com.android.systemui.shared.Flags.returnAnimationFrameworkLibrary;
+import static com.android.window.flags.Flags.migratePredictiveBackTransition;
import static com.android.wm.shell.shared.TransitionUtil.isClosingType;
import static com.android.wm.shell.shared.TransitionUtil.isOpeningType;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_SHELL_TRANSITIONS;
@@ -822,7 +822,8 @@
}
// The change has already animated by back gesture, don't need to play transition
// animation on it.
- if (change.hasFlags(FLAG_BACK_GESTURE_ANIMATED)) {
+ if (!migratePredictiveBackTransition()
+ && change.hasFlags(FLAG_BACK_GESTURE_ANIMATED)) {
info.getChanges().remove(i);
}
}
@@ -936,9 +937,7 @@
}
private void onMerged(@NonNull IBinder playingToken, @NonNull IBinder mergedToken) {
- if (enforceShellThreadModel()) {
- mMainExecutor.assertCurrentThread();
- }
+ mMainExecutor.assertCurrentThread();
ActiveTransition playing = mKnownTransitions.get(playingToken);
if (playing == null) {
@@ -1087,9 +1086,7 @@
}
private void onFinish(IBinder token, @Nullable WindowContainerTransaction wct) {
- if (enforceShellThreadModel()) {
- mMainExecutor.assertCurrentThread();
- }
+ mMainExecutor.assertCurrentThread();
final ActiveTransition active = mKnownTransitions.get(token);
if (active == null) {
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 5c230c0..d8dba71 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
@@ -33,6 +33,7 @@
import android.hardware.input.InputManager;
import android.os.Handler;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
import android.util.SparseArray;
@@ -288,6 +289,7 @@
final CaptionWindowDecoration windowDecoration =
new CaptionWindowDecoration(
mContext,
+ mContext.createContextAsUser(UserHandle.of(taskInfo.userId), 0 /* flags */),
mDisplayController,
mTaskOrganizer,
taskInfo,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
index cf42a49..401b78d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
@@ -30,6 +30,7 @@
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Color;
+import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.GradientDrawable;
@@ -37,10 +38,12 @@
import android.os.Handler;
import android.util.Size;
import android.view.Choreographer;
+import android.view.InsetsState;
import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.View;
import android.view.ViewConfiguration;
+import android.view.WindowInsets;
import android.view.WindowManager;
import android.window.WindowContainerTransaction;
@@ -77,6 +80,7 @@
CaptionWindowDecoration(
Context context,
+ @NonNull Context userContext,
DisplayController displayController,
ShellTaskOrganizer taskOrganizer,
RunningTaskInfo taskInfo,
@@ -85,7 +89,7 @@
@ShellBackgroundThread ShellExecutor bgExecutor,
Choreographer choreographer,
SyncTransactionQueue syncQueue) {
- super(context, displayController, taskOrganizer, taskInfo, taskSurface);
+ super(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface);
mHandler = handler;
mBgExecutor = bgExecutor;
mChoreographer = choreographer;
@@ -194,7 +198,8 @@
RelayoutParams relayoutParams,
ActivityManager.RunningTaskInfo taskInfo,
boolean applyStartTransactionOnDraw,
- boolean setTaskCropAndPosition) {
+ boolean setTaskCropAndPosition,
+ InsetsState displayInsetsState) {
relayoutParams.reset();
relayoutParams.mRunningTaskInfo = taskInfo;
relayoutParams.mLayoutResId = R.layout.caption_window_decor;
@@ -222,6 +227,8 @@
controlsElement.mWidthResId = R.dimen.caption_right_buttons_width;
controlsElement.mAlignment = RelayoutParams.OccludingCaptionElement.Alignment.END;
relayoutParams.mOccludingCaptionElements.add(controlsElement);
+ relayoutParams.mCaptionTopPadding = getTopPadding(relayoutParams,
+ taskInfo.getConfiguration().windowConfiguration.getBounds(), displayInsetsState);
}
@SuppressLint("MissingPermission")
@@ -237,7 +244,7 @@
final WindowContainerTransaction wct = new WindowContainerTransaction();
updateRelayoutParams(mRelayoutParams, taskInfo, applyStartTransactionOnDraw,
- setTaskCropAndPosition);
+ setTaskCropAndPosition, mDisplayController.getInsetsState(taskInfo.displayId));
relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
// After this line, mTaskInfo is up-to-date and should be used instead of taskInfo
@@ -278,7 +285,7 @@
final Resources res = mResult.mRootView.getResources();
mDragResizeListener.setGeometry(new DragResizeWindowGeometry(0 /* taskCornerRadius */,
- new Size(mResult.mWidth, mResult.mHeight), getResizeEdgeHandleSize(res),
+ new Size(mResult.mWidth, mResult.mHeight), getResizeEdgeHandleSize(mContext, res),
getFineResizeCornerSize(res), getLargeResizeCornerSize(res)), touchSlop);
}
@@ -343,6 +350,18 @@
mDragResizeListener = null;
}
+ private static int getTopPadding(RelayoutParams params, Rect taskBounds,
+ InsetsState insetsState) {
+ if (!params.mRunningTaskInfo.isFreeform()) {
+ Insets systemDecor = insetsState.calculateInsets(taskBounds,
+ WindowInsets.Type.systemBars() & ~WindowInsets.Type.captionBar(),
+ false /* ignoreVisibility */);
+ return systemDecor.top;
+ } else {
+ return 0;
+ }
+ }
+
/**
* Checks whether the touch event falls inside the customizable caption region.
*/
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 0ff3522..a242b8a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -30,7 +30,6 @@
import static android.view.MotionEvent.ACTION_HOVER_ENTER;
import static android.view.MotionEvent.ACTION_HOVER_EXIT;
import static android.view.MotionEvent.ACTION_MOVE;
-import static android.view.MotionEvent.ACTION_OUTSIDE;
import static android.view.MotionEvent.ACTION_UP;
import static android.view.WindowInsets.Type.statusBars;
@@ -59,6 +58,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.Log;
import android.util.SparseArray;
import android.view.Choreographer;
@@ -89,9 +89,11 @@
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser;
+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.MultiInstanceHelper;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource;
@@ -116,6 +118,8 @@
import com.android.wm.shell.windowdecor.extension.TaskInfoKt;
import com.android.wm.shell.windowdecor.viewholder.AppHeaderViewHolder;
+import kotlin.Unit;
+
import java.io.PrintWriter;
import java.util.Optional;
import java.util.function.Supplier;
@@ -144,6 +148,7 @@
private final DesktopTasksController mDesktopTasksController;
private final InputManager mInputManager;
private final InteractionJankMonitor mInteractionJankMonitor;
+ private final MultiInstanceHelper mMultiInstanceHelper;
private boolean mTransitionDragActive;
private SparseArray<EventReceiver> mEventReceiversByDisplay = new SparseArray<>();
@@ -171,6 +176,7 @@
private boolean mInImmersiveMode;
private final String mSysUIPackageName;
+ private final DisplayChangeController.OnDisplayChangingListener mOnDisplayChangingListener;
private final ISystemGestureExclusionListener mGestureExclusionListener =
new ISystemGestureExclusionListener.Stub() {
@Override
@@ -203,7 +209,8 @@
Optional<DesktopTasksController> desktopTasksController,
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
InteractionJankMonitor interactionJankMonitor,
- AppToWebGenericLinksParser genericLinksParser
+ AppToWebGenericLinksParser genericLinksParser,
+ MultiInstanceHelper multiInstanceHelper
) {
this(
context,
@@ -222,6 +229,7 @@
transitions,
desktopTasksController,
genericLinksParser,
+ multiInstanceHelper,
new DesktopModeWindowDecoration.Factory(),
new InputMonitorFactory(),
SurfaceControl.Transaction::new,
@@ -248,6 +256,7 @@
Transitions transitions,
Optional<DesktopTasksController> desktopTasksController,
AppToWebGenericLinksParser genericLinksParser,
+ MultiInstanceHelper multiInstanceHelper,
DesktopModeWindowDecoration.Factory desktopModeWindowDecorFactory,
InputMonitorFactory inputMonitorFactory,
Supplier<SurfaceControl.Transaction> transactionFactory,
@@ -267,6 +276,7 @@
mSyncQueue = syncQueue;
mTransitions = transitions;
mDesktopTasksController = desktopTasksController.get();
+ mMultiInstanceHelper = multiInstanceHelper;
mShellCommandHandler = shellCommandHandler;
mWindowManager = windowManager;
mDesktopModeWindowDecorFactory = desktopModeWindowDecorFactory;
@@ -279,6 +289,31 @@
mSysUIPackageName = mContext.getResources().getString(
com.android.internal.R.string.config_systemUi);
mInteractionJankMonitor = interactionJankMonitor;
+ mOnDisplayChangingListener = (displayId, fromRotation, toRotation, displayAreaInfo, t) -> {
+ DesktopModeWindowDecoration decoration;
+ RunningTaskInfo taskInfo;
+ for (int i = 0; i < mWindowDecorByTaskId.size(); i++) {
+ decoration = mWindowDecorByTaskId.valueAt(i);
+ if (decoration == null) {
+ continue;
+ } else {
+ taskInfo = decoration.mTaskInfo;
+ }
+
+ // Check if display has been rotated between portrait & landscape
+ if (displayId == taskInfo.displayId && taskInfo.isFreeform()
+ && (fromRotation % 2 != toRotation % 2)) {
+ // Check if the task bounds on the rotated display will be out of bounds.
+ // If so, then update task bounds to be within reachable area.
+ final Rect taskBounds = new Rect(
+ taskInfo.configuration.windowConfiguration.getBounds());
+ if (DragPositioningCallbackUtility.snapTaskBoundsIfNecessary(
+ taskBounds, decoration.calculateValidDragArea())) {
+ t.setBounds(taskInfo.token, taskBounds);
+ }
+ }
+ }
+ };
shellInit.addInitCallback(this::onInit, this);
}
@@ -289,7 +324,10 @@
mDisplayInsetsController.addInsetsChangedListener(mContext.getDisplayId(),
new DesktopModeOnInsetsChangedListener());
mDesktopTasksController.setOnTaskResizeAnimationListener(
- new DeskopModeOnTaskResizeAnimationListener());
+ new DesktopModeOnTaskResizeAnimationListener());
+ mDesktopTasksController.setOnTaskRepositionAnimationListener(
+ new DesktopModeOnTaskRepositionAnimationListener());
+ mDisplayController.addDisplayChangingController(mOnDisplayChangingListener);
try {
mWindowManager.registerSystemGestureExclusionListener(mGestureExclusionListener,
mContext.getDisplayId());
@@ -411,13 +449,13 @@
mWindowDecorByTaskId.remove(taskInfo.taskId);
}
- private void onMaximizeOrRestore(int taskId, String tag) {
+ private void onMaximizeOrRestore(int taskId, String source) {
final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId);
if (decoration == null) {
return;
}
mInteractionJankMonitor.begin(
- decoration.mTaskSurface, mContext, Cuj.CUJ_DESKTOP_MODE_MAXIMIZE_WINDOW, tag);
+ decoration.mTaskSurface, mContext, Cuj.CUJ_DESKTOP_MODE_MAXIMIZE_WINDOW, source);
mDesktopTasksController.toggleDesktopTaskSize(decoration.mTaskInfo);
decoration.closeHandleMenu();
decoration.closeMaximizeMenu();
@@ -428,16 +466,28 @@
if (decoration == null) {
return;
}
- mDesktopTasksController.snapToHalfScreen(decoration.mTaskInfo,
- left ? SnapPosition.LEFT : SnapPosition.RIGHT);
+
+ if (!decoration.mTaskInfo.isResizeable
+ && DesktopModeFlags.DISABLE_SNAP_RESIZE.isEnabled(mContext)) {
+ //TODO(b/354658237) - show toast with relevant string
+ } else {
+ mDesktopTasksController.snapToHalfScreen(decoration.mTaskInfo,
+ decoration.mTaskInfo.configuration.windowConfiguration.getBounds(),
+ left ? SnapPosition.LEFT : SnapPosition.RIGHT);
+ }
+
decoration.closeHandleMenu();
decoration.closeMaximizeMenu();
}
- private void onOpenInBrowser(@NonNull DesktopModeWindowDecoration decor, @NonNull Uri uri) {
+ private void onOpenInBrowser(int taskId, @NonNull Uri uri) {
+ final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId);
+ if (decoration == null) {
+ return;
+ }
openInBrowser(uri);
- decor.closeHandleMenu();
- decor.closeMaximizeMenu();
+ decoration.closeHandleMenu();
+ decoration.closeMaximizeMenu();
}
private void openInBrowser(Uri uri) {
@@ -447,6 +497,57 @@
mContext.startActivity(intent);
}
+ private void onToDesktop(int taskId, DesktopModeTransitionSource source) {
+ final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId);
+ if (decoration == null) {
+ return;
+ }
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ mInteractionJankMonitor.begin(decoration.mTaskSurface, mContext,
+ CUJ_DESKTOP_MODE_ENTER_MODE_APP_HANDLE_MENU);
+ // App sometimes draws before the insets from WindowDecoration#relayout have
+ // been added, so they must be added here
+ decoration.addCaptionInset(wct);
+ mDesktopTasksController.moveTaskToDesktop(taskId, wct, source);
+ decoration.closeHandleMenu();
+ }
+
+ private void onToFullscreen(int taskId) {
+ final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId);
+ if (decoration == null) {
+ return;
+ }
+ decoration.closeHandleMenu();
+ if (isTaskInSplitScreen(taskId)) {
+ mSplitScreenController.moveTaskToFullscreen(taskId,
+ SplitScreenController.EXIT_REASON_DESKTOP_MODE);
+ } else {
+ mDesktopTasksController.moveToFullscreen(taskId,
+ DesktopModeTransitionSource.APP_HANDLE_MENU_BUTTON);
+ }
+ }
+
+ private void onToSplitScreen(int taskId) {
+ final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId);
+ if (decoration == null) {
+ return;
+ }
+ decoration.closeHandleMenu();
+ // When the app enters split-select, the handle will no longer be visible, meaning
+ // we shouldn't receive input for it any longer.
+ decoration.disposeStatusBarInputLayer();
+ mDesktopTasksController.requestSplit(decoration.mTaskInfo, false /* leftOrTop */);
+ }
+
+ private void onNewWindow(int taskId) {
+ final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId);
+ if (decoration == null) {
+ return;
+ }
+ decoration.closeHandleMenu();
+ mDesktopTasksController.openNewWindow(decoration.mTaskInfo);
+ }
+
private class DesktopModeTouchEventListener extends GestureDetector.SimpleOnGestureListener
implements View.OnClickListener, View.OnTouchListener, View.OnLongClickListener,
View.OnGenericMotionListener, DragDetector.MotionEventHandler {
@@ -457,6 +558,7 @@
private final DragDetector mDragDetector;
private final GestureDetector mGestureDetector;
private final int mDisplayId;
+ private final Rect mOnDragStartInitialBounds = new Rect();
/**
* Whether to pilfer the next motion event to send cancellations to the windows below.
@@ -504,37 +606,6 @@
moveTaskToFront(decoration.mTaskInfo);
decoration.createHandleMenu(mSplitScreenController);
}
- } else if (id == R.id.desktop_button) {
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- // App sometimes draws before the insets from WindowDecoration#relayout have
- // been added, so they must be added here
- mInteractionJankMonitor.begin(decoration.mTaskSurface, mContext,
- CUJ_DESKTOP_MODE_ENTER_MODE_APP_HANDLE_MENU);
- mWindowDecorByTaskId.get(mTaskId).addCaptionInset(wct);
- mDesktopTasksController.moveToDesktop(mTaskId, wct,
- DesktopModeTransitionSource.APP_HANDLE_MENU_BUTTON);
- decoration.closeHandleMenu();
- } else if (id == R.id.fullscreen_button) {
- decoration.closeHandleMenu();
- if (isTaskInSplitScreen(mTaskId)) {
- mSplitScreenController.moveTaskToFullscreen(mTaskId,
- SplitScreenController.EXIT_REASON_DESKTOP_MODE);
- } else {
- mDesktopTasksController.moveToFullscreen(mTaskId,
- DesktopModeTransitionSource.APP_HANDLE_MENU_BUTTON);
- }
- } else if (id == R.id.split_screen_button) {
- decoration.closeHandleMenu();
- // When the app enters split-select, the handle will no longer be visible, meaning
- // we shouldn't receive input for it any longer.
- decoration.disposeStatusBarInputLayer();
- mDesktopTasksController.requestSplit(decoration.mTaskInfo);
- } else if (id == R.id.open_in_browser_button) {
- // TODO(b/346441962): let the decoration handle the click gesture and only call back
- // to the ViewModel via #setOpenInBrowserClickListener
- decoration.onOpenInBrowserClick();
- } else if (id == R.id.collapse_menu_button) {
- decoration.closeHandleMenu();
} else if (id == R.id.maximize_window) {
// TODO(b/346441962): move click detection logic into the decor's
// {@link AppHeaderViewHolder}. Let it encapsulate the that and have it report
@@ -549,16 +620,6 @@
public boolean onTouch(View v, MotionEvent e) {
final int id = v.getId();
final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId);
- if (e.getActionMasked() == ACTION_OUTSIDE) {
- if (id == R.id.handle_menu) {
- // Close handle menu on outside touch if menu is directly touchable; if not,
- // it will be handled by handleEventOutsideCaption.
- if (decoration.mTaskInfo.isFreeform()
- || Flags.enableAdditionalWindowsAboveStatusBar()) {
- decoration.closeHandleMenu();
- }
- }
- }
if ((e.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN) {
mTouchscreenInUse = e.getActionMasked() != ACTION_UP
&& e.getActionMasked() != ACTION_CANCEL;
@@ -568,13 +629,21 @@
&& id != R.id.maximize_window) {
return false;
}
- moveTaskToFront(decoration.mTaskInfo);
final int actionMasked = e.getActionMasked();
final boolean isDown = actionMasked == MotionEvent.ACTION_DOWN;
final boolean isUpOrCancel = actionMasked == MotionEvent.ACTION_CANCEL
|| actionMasked == MotionEvent.ACTION_UP;
if (isDown) {
+ // Only move to front on down to prevent 2+ tasks from fighting
+ // (and thus flickering) for front status when drag-moving them simultaneously with
+ // two pointers.
+ // TODO(b/356962065): during a drag-move, this shouldn't be a WCT - just move the
+ // task surface to the top of other tasks and reorder once the user releases the
+ // gesture together with the bounds' WCT. This is probably still valid for other
+ // gestures like simple clicks.
+ moveTaskToFront(decoration.mTaskInfo);
+
final boolean downInCustomizableCaptionRegion =
decoration.checkTouchEventInCustomizableRegion(e);
final boolean downInExclusionRegion = mExclusionRegion.contains(
@@ -701,10 +770,11 @@
switch (e.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
mDragPointerId = e.getPointerId(0);
- mDragPositioningCallback.onDragPositioningStart(
+ final Rect initialBounds = mDragPositioningCallback.onDragPositioningStart(
0 /* ctrlType */, e.getRawX(0),
e.getRawY(0));
updateDragStatus(e.getActionMasked());
+ mOnDragStartInitialBounds.set(initialBounds);
mHasLongClicked = false;
// Do not consume input event if a button is touched, otherwise it would
// prevent the button's ripple effect from showing.
@@ -745,9 +815,14 @@
(int) (e.getRawY(dragPointerIdx) - e.getY(dragPointerIdx)));
final Rect newTaskBounds = mDragPositioningCallback.onDragPositioningEnd(
e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
- mDesktopTasksController.onDragPositioningEnd(taskInfo, position,
+ // Tasks bounds haven't actually been updated (only its leash), so pass to
+ // DesktopTasksController to allow secondary transformations (i.e. snap resizing
+ // or transforming to fullscreen) before setting new task bounds.
+ mDesktopTasksController.onDragPositioningEnd(
+ taskInfo, decoration.mTaskSurface, position,
new PointF(e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx)),
- newTaskBounds, decoration.calculateValidDragArea());
+ newTaskBounds, decoration.calculateValidDragArea(),
+ new Rect(mOnDragStartInitialBounds));
if (touchingButton && !mHasLongClicked) {
// We need the input event to not be consumed here to end the ripple
// effect on the touched button. We will reset drag state in the ensuing
@@ -1149,6 +1224,7 @@
final DesktopModeWindowDecoration windowDecoration =
mDesktopModeWindowDecorFactory.create(
mContext,
+ mContext.createContextAsUser(UserHandle.of(taskInfo.userId), 0 /* flags */),
mDisplayController,
mSplitScreenController,
mTaskOrganizer,
@@ -1159,18 +1235,19 @@
mMainChoreographer,
mSyncQueue,
mRootTaskDisplayAreaOrganizer,
- mGenericLinksParser);
+ mGenericLinksParser,
+ mMultiInstanceHelper);
mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
final DragPositioningCallback dragPositioningCallback;
if (!DesktopModeStatus.isVeiledResizeEnabled()) {
- dragPositioningCallback = new FluidResizeTaskPositioner(
+ dragPositioningCallback = new FluidResizeTaskPositioner(
mTaskOrganizer, mTransitions, windowDecoration, mDisplayController,
mDragStartListener, mTransactionFactory);
windowDecoration.setTaskDragResizer(
(FluidResizeTaskPositioner) dragPositioningCallback);
} else {
- dragPositioningCallback = new VeiledResizeTaskPositioner(
+ dragPositioningCallback = new VeiledResizeTaskPositioner(
mTaskOrganizer, windowDecoration, mDisplayController,
mDragStartListener, mTransitions, mInteractionJankMonitor);
windowDecoration.setTaskDragResizer(
@@ -1179,14 +1256,36 @@
final DesktopModeTouchEventListener touchEventListener =
new DesktopModeTouchEventListener(taskInfo, dragPositioningCallback);
- windowDecoration.setOnMaximizeOrRestoreClickListener(this::onMaximizeOrRestore);
- windowDecoration.setOnLeftSnapClickListener((taskId, tag) -> {
- onSnapResize(taskId, true /* isLeft */);
+ windowDecoration.setOnMaximizeOrRestoreClickListener(() -> {
+ onMaximizeOrRestore(taskInfo.taskId, "maximize_menu");
+ return Unit.INSTANCE;
});
- windowDecoration.setOnRightSnapClickListener((taskId, tag) -> {
- onSnapResize(taskId, false /* isLeft */);
+ windowDecoration.setOnLeftSnapClickListener(() -> {
+ onSnapResize(taskInfo.taskId, true /* isLeft */);
+ return Unit.INSTANCE;
});
- windowDecoration.setOpenInBrowserClickListener(this::onOpenInBrowser);
+ windowDecoration.setOnRightSnapClickListener(() -> {
+ onSnapResize(taskInfo.taskId, false /* isLeft */);
+ return Unit.INSTANCE;
+ });
+ windowDecoration.setOnToDesktopClickListener(desktopModeTransitionSource -> {
+ onToDesktop(taskInfo.taskId, desktopModeTransitionSource);
+ });
+ windowDecoration.setOnToFullscreenClickListener(() -> {
+ onToFullscreen(taskInfo.taskId);
+ return Unit.INSTANCE;
+ });
+ windowDecoration.setOnToSplitScreenClickListener(() -> {
+ onToSplitScreen(taskInfo.taskId);
+ return Unit.INSTANCE;
+ });
+ windowDecoration.setOpenInBrowserClickListener((uri) -> {
+ onOpenInBrowser(taskInfo.taskId, uri);
+ });
+ windowDecoration.setOnNewWindowClickListener(() -> {
+ onNewWindow(taskInfo.taskId);
+ return Unit.INSTANCE;
+ });
windowDecoration.setCaptionListeners(
touchEventListener, touchEventListener, touchEventListener, touchEventListener);
windowDecoration.setExclusionRegionListener(mExclusionRegionListener);
@@ -1221,7 +1320,26 @@
pw.println(innerPrefix + "mWindowDecorByTaskId=" + mWindowDecorByTaskId);
}
- private class DeskopModeOnTaskResizeAnimationListener
+ private class DesktopModeOnTaskRepositionAnimationListener
+ implements OnTaskRepositionAnimationListener {
+ @Override
+ public void onAnimationStart(int taskId) {
+ final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId);
+ if (decoration != null) {
+ decoration.setAnimatingTaskResizeOrReposition(true);
+ }
+ }
+
+ @Override
+ public void onAnimationEnd(int taskId) {
+ final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId);
+ if (decoration != null) {
+ decoration.setAnimatingTaskResizeOrReposition(false);
+ }
+ }
+ }
+
+ private class DesktopModeOnTaskResizeAnimationListener
implements OnTaskResizeAnimationListener {
@Override
public void onAnimationStart(int taskId, Transaction t, Rect bounds) {
@@ -1231,7 +1349,7 @@
return;
}
decoration.showResizeVeil(t, bounds);
- decoration.setAnimatingTaskResize(true);
+ decoration.setAnimatingTaskResizeOrReposition(true);
}
@Override
@@ -1246,7 +1364,7 @@
final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId);
if (decoration == null) return;
decoration.hideResizeVeil();
- decoration.setAnimatingTaskResize(false);
+ decoration.setAnimatingTaskResizeOrReposition(false);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 41f428b..538d0fb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -26,6 +26,7 @@
import static android.view.MotionEvent.ACTION_UP;
import static com.android.launcher3.icons.BaseIconFactory.MODE_DEFAULT;
+import static com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource.APP_HANDLE_MENU_BUTTON;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getFineResizeCornerSize;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getLargeResizeCornerSize;
@@ -74,20 +75,23 @@
import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
+import com.android.wm.shell.common.MultiInstanceHelper;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource;
import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
import com.android.wm.shell.shared.desktopmode.DesktopModeFlags;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import com.android.wm.shell.splitscreen.SplitScreenController;
-import com.android.wm.shell.windowdecor.common.OnTaskActionClickListener;
import com.android.wm.shell.windowdecor.extension.TaskInfoKt;
import com.android.wm.shell.windowdecor.viewholder.AppHandleViewHolder;
import com.android.wm.shell.windowdecor.viewholder.AppHeaderViewHolder;
import com.android.wm.shell.windowdecor.viewholder.WindowDecorationViewHolder;
import kotlin.Unit;
+import kotlin.jvm.functions.Function0;
+import java.util.function.Consumer;
import java.util.function.Supplier;
/**
@@ -114,9 +118,13 @@
private View.OnTouchListener mOnCaptionTouchListener;
private View.OnLongClickListener mOnCaptionLongClickListener;
private View.OnGenericMotionListener mOnCaptionGenericMotionListener;
- private OnTaskActionClickListener mOnMaximizeOrRestoreClickListener;
- private OnTaskActionClickListener mOnLeftSnapClickListener;
- private OnTaskActionClickListener mOnRightSnapClickListener;
+ private Function0<Unit> mOnMaximizeOrRestoreClickListener;
+ private Function0<Unit> mOnLeftSnapClickListener;
+ private Function0<Unit> mOnRightSnapClickListener;
+ private Consumer<DesktopModeTransitionSource> mOnToDesktopClickListener;
+ private Function0<Unit> mOnToFullscreenClickListener;
+ private Function0<Unit> mOnToSplitscreenClickListener;
+ private Function0<Unit> mOnNewWindowClickListener;
private DragPositioningCallback mDragPositioningCallback;
private DragResizeInputListener mDragResizeListener;
private DragDetector mDragDetector;
@@ -139,7 +147,7 @@
private CharSequence mAppName;
private CapturedLink mCapturedLink;
private Uri mGenericLink;
- private OpenInBrowserClickListener mOpenInBrowserClickListener;
+ private Consumer<Uri> mOpenInBrowserClickListener;
private ExclusionRegionListener mExclusionRegionListener;
@@ -157,9 +165,11 @@
// to cancel the close.
private final Runnable mCloseMaximizeWindowRunnable = this::closeMaximizeMenu;
private final Runnable mCapturedLinkExpiredRunnable = this::onCapturedLinkExpired;
+ private final MultiInstanceHelper mMultiInstanceHelper;
DesktopModeWindowDecoration(
Context context,
+ @NonNull Context userContext,
DisplayController displayController,
SplitScreenController splitScreenController,
ShellTaskOrganizer taskOrganizer,
@@ -170,17 +180,20 @@
Choreographer choreographer,
SyncTransactionQueue syncQueue,
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
- AppToWebGenericLinksParser genericLinksParser) {
- this (context, displayController, splitScreenController, taskOrganizer, taskInfo,
- taskSurface, handler, bgExecutor, choreographer, syncQueue,
+ AppToWebGenericLinksParser genericLinksParser,
+ MultiInstanceHelper multiInstanceHelper) {
+ this (context, userContext, displayController, splitScreenController, taskOrganizer,
+ taskInfo, taskSurface, handler, bgExecutor, choreographer, syncQueue,
rootTaskDisplayAreaOrganizer, genericLinksParser, SurfaceControl.Builder::new,
SurfaceControl.Transaction::new, WindowContainerTransaction::new,
SurfaceControl::new, new SurfaceControlViewHostFactory() {},
- DefaultMaximizeMenuFactory.INSTANCE, DefaultHandleMenuFactory.INSTANCE);
+ DefaultMaximizeMenuFactory.INSTANCE, DefaultHandleMenuFactory.INSTANCE,
+ multiInstanceHelper);
}
DesktopModeWindowDecoration(
Context context,
+ @NonNull Context userContext,
DisplayController displayController,
SplitScreenController splitScreenController,
ShellTaskOrganizer taskOrganizer,
@@ -198,8 +211,9 @@
Supplier<SurfaceControl> surfaceControlSupplier,
SurfaceControlViewHostFactory surfaceControlViewHostFactory,
MaximizeMenuFactory maximizeMenuFactory,
- HandleMenuFactory handleMenuFactory) {
- super(context, displayController, taskOrganizer, taskInfo, taskSurface,
+ HandleMenuFactory handleMenuFactory,
+ MultiInstanceHelper multiInstanceHelper) {
+ super(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface,
surfaceControlBuilderSupplier, surfaceControlTransactionSupplier,
windowContainerTransactionSupplier, surfaceControlSupplier,
surfaceControlViewHostFactory);
@@ -212,6 +226,7 @@
mGenericLinksParser = genericLinksParser;
mMaximizeMenuFactory = maximizeMenuFactory;
mHandleMenuFactory = handleMenuFactory;
+ mMultiInstanceHelper = multiInstanceHelper;
}
/**
@@ -220,24 +235,42 @@
* TODO(b/346441962): hook this up to double-tap and the header's maximize button, instead of
* having the ViewModel deal with parsing motion events.
*/
- void setOnMaximizeOrRestoreClickListener(OnTaskActionClickListener listener) {
+ void setOnMaximizeOrRestoreClickListener(Function0<Unit> listener) {
mOnMaximizeOrRestoreClickListener = listener;
}
- /**
- * Register a listener to be called back when one of the tasks snap-left action is triggered.
- */
- void setOnLeftSnapClickListener(OnTaskActionClickListener listener) {
+ /** Registers a listener to be called when the decoration's snap-left action is triggered.*/
+ void setOnLeftSnapClickListener(Function0<Unit> listener) {
mOnLeftSnapClickListener = listener;
}
- /**
- * Register a listener to be called back when one of the tasks' snap-right action is triggered.
- */
- void setOnRightSnapClickListener(OnTaskActionClickListener listener) {
+ /** Registers a listener to be called when the decoration's snap-right action is triggered. */
+ void setOnRightSnapClickListener(Function0<Unit> listener) {
mOnRightSnapClickListener = listener;
}
+ /** Registers a listener to be called when the decoration's to-desktop action is triggered. */
+ void setOnToDesktopClickListener(Consumer<DesktopModeTransitionSource> listener) {
+ mOnToDesktopClickListener = listener;
+ }
+
+ /**
+ * Registers a listener to be called when the decoration's to-fullscreen action is triggered.
+ */
+ void setOnToFullscreenClickListener(Function0<Unit> listener) {
+ mOnToFullscreenClickListener = listener;
+ }
+
+ /** Registers a listener to be called when the decoration's to-split action is triggered. */
+ void setOnToSplitScreenClickListener(Function0<Unit> listener) {
+ mOnToSplitscreenClickListener = listener;
+ }
+
+ /** Registers a listener to be called when the decoration's new window action is triggered. */
+ void setOnNewWindowClickListener(Function0<Unit> listener) {
+ mOnNewWindowClickListener = listener;
+ }
+
void setCaptionListeners(
View.OnClickListener onCaptionButtonClickListener,
View.OnTouchListener onCaptionTouchListener,
@@ -262,7 +295,7 @@
mDragDetector.setTouchSlop(ViewConfiguration.get(mContext).getScaledTouchSlop());
}
- void setOpenInBrowserClickListener(OpenInBrowserClickListener listener) {
+ void setOpenInBrowserClickListener(Consumer<Uri> listener) {
mOpenInBrowserClickListener = listener;
}
@@ -279,8 +312,7 @@
// transaction (that applies task crop) is synced with the buffer transaction (that draws
// the View). Both will be shown on screen at the same, whereas applying them independently
// causes flickering. See b/270202228.
- final boolean applyTransactionOnDraw =
- taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM;
+ final boolean applyTransactionOnDraw = taskInfo.isFreeform();
relayout(taskInfo, t, t, applyTransactionOnDraw, shouldSetTaskPositionAndCrop);
if (!applyTransactionOnDraw) {
t.apply();
@@ -291,7 +323,7 @@
SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop) {
Trace.beginSection("DesktopModeWindowDecoration#relayout");
- if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
+ if (taskInfo.isFreeform()) {
// The Task is in Freeform mode -> show its header in sync since it's an integral part
// of the window itself - a delayed header might cause bad UX.
relayoutInSync(taskInfo, startT, finishT, applyStartTransactionOnDraw,
@@ -437,14 +469,6 @@
}
}
- void onOpenInBrowserClick() {
- if (mOpenInBrowserClickListener == null || mHandleMenu == null) {
- return;
- }
- mOpenInBrowserClickListener.onClick(this, mHandleMenu.getOpenInBrowserLink());
- onCapturedLinkExpired();
- }
-
@Nullable
private Uri getBrowserLink() {
// If the captured link is available and has not expired, return the captured link.
@@ -490,17 +514,16 @@
final Resources res = mResult.mRootView.getResources();
if (mDragResizeListener.setGeometry(
new DragResizeWindowGeometry(mRelayoutParams.mCornerRadius,
- new Size(mResult.mWidth, mResult.mHeight), getResizeEdgeHandleSize(res),
- getFineResizeCornerSize(res), getLargeResizeCornerSize(res)), touchSlop)
+ new Size(mResult.mWidth, mResult.mHeight),
+ getResizeEdgeHandleSize(mContext, res), getFineResizeCornerSize(res),
+ getLargeResizeCornerSize(res)), touchSlop)
|| !mTaskInfo.positionInParent.equals(mPositionInParent)) {
updateExclusionRegion();
}
}
private static boolean isDragResizable(ActivityManager.RunningTaskInfo taskInfo) {
- final boolean isFreeform =
- taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM;
- return isFreeform && taskInfo.isResizeable;
+ return taskInfo.isFreeform() && taskInfo.isResizeable;
}
private void updateMaximizeMenu(SurfaceControl.Transaction startT) {
@@ -737,12 +760,8 @@
Slog.e(TAG, "Base activity component not found in task");
return;
}
- final PackageManager pm = mContext.getApplicationContext().getPackageManager();
- final ActivityInfo activityInfo = pm.getActivityInfo(baseActivity,
- // Include uninstalled apps. Despite its name, adding this flag is a workaround
- // to #getActivityInfo throwing a NameNotFoundException for installed packages
- // when HSUM is enabled. See b/354884302.
- PackageManager.MATCH_UNINSTALLED_PACKAGES);
+ final PackageManager pm = mUserContext.getPackageManager();
+ final ActivityInfo activityInfo = pm.getActivityInfo(baseActivity, 0 /* flags */);
final IconProvider provider = new IconProvider(mContext);
final Drawable appIconDrawable = provider.getIcon(activityInfo);
final BaseIconFactory headerIconFactory = createIconFactory(mContext,
@@ -960,20 +979,41 @@
mHandleMenu = mHandleMenuFactory.create(
this,
mRelayoutParams.mLayoutResId,
- mOnCaptionButtonClickListener,
- mOnCaptionTouchListener,
mAppIconBitmap,
mAppName,
- mDisplayController,
splitScreenController,
DesktopModeStatus.canEnterDesktopMode(mContext),
+ Flags.enableDesktopWindowingMultiInstanceFeatures()
+ && mMultiInstanceHelper
+ .supportsMultiInstanceSplit(mTaskInfo.baseActivity),
getBrowserLink(),
mResult.mCaptionWidth,
mResult.mCaptionHeight,
mResult.mCaptionX
);
mWindowDecorViewHolder.onHandleMenuOpened();
- mHandleMenu.show();
+ mHandleMenu.show(
+ /* onToDesktopClickListener= */ () -> {
+ mOnToDesktopClickListener.accept(APP_HANDLE_MENU_BUTTON);
+ return Unit.INSTANCE;
+ },
+ /* onToFullscreenClickListener= */ mOnToFullscreenClickListener,
+ /* onToSplitScreenClickListener= */ mOnToSplitscreenClickListener,
+ /* onNewWindowClickListener= */ mOnNewWindowClickListener,
+ /* openInBrowserClickListener= */ (uri) -> {
+ mOpenInBrowserClickListener.accept(uri);
+ onCapturedLinkExpired();
+ return Unit.INSTANCE;
+ },
+ /* onCloseMenuClickListener= */ () -> {
+ closeHandleMenu();
+ return Unit.INSTANCE;
+ },
+ /* onOutsideTouchListener= */ () -> {
+ closeHandleMenu();
+ return Unit.INSTANCE;
+ }
+ );
}
private void updateGenericLink() {
@@ -1228,10 +1268,10 @@
return R.id.desktop_mode_caption;
}
- void setAnimatingTaskResize(boolean animatingTaskResize) {
+ void setAnimatingTaskResizeOrReposition(boolean animatingTaskResizeOrReposition) {
if (mRelayoutParams.mLayoutResId == R.layout.desktop_mode_app_handle) return;
((AppHeaderViewHolder) mWindowDecorViewHolder)
- .setAnimatingTaskResize(animatingTaskResize);
+ .setAnimatingTaskResizeOrReposition(animatingTaskResizeOrReposition);
}
/**
@@ -1264,6 +1304,7 @@
DesktopModeWindowDecoration create(
Context context,
+ @NonNull Context userContext,
DisplayController displayController,
SplitScreenController splitScreenController,
ShellTaskOrganizer taskOrganizer,
@@ -1274,9 +1315,11 @@
Choreographer choreographer,
SyncTransactionQueue syncQueue,
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
- AppToWebGenericLinksParser genericLinksParser) {
+ AppToWebGenericLinksParser genericLinksParser,
+ MultiInstanceHelper multiInstanceHelper) {
return new DesktopModeWindowDecoration(
context,
+ userContext,
displayController,
splitScreenController,
taskOrganizer,
@@ -1287,7 +1330,8 @@
choreographer,
syncQueue,
rootTaskDisplayAreaOrganizer,
- genericLinksParser);
+ genericLinksParser,
+ multiInstanceHelper);
}
}
@@ -1308,14 +1352,6 @@
}
}
-
- /** Listener for the handle menu's "Open in browser" button */
- interface OpenInBrowserClickListener {
-
- /** Inform the implementing class that the "Open in browser" button has been clicked */
- void onClick(DesktopModeWindowDecoration decoration, Uri uri);
- }
-
interface ExclusionRegionListener {
/** Inform the implementing class of this task's change in region resize handles */
void onExclusionRegionChanged(int taskId, Region region);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
index 32df8b3..a27c506 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
@@ -17,6 +17,7 @@
package com.android.wm.shell.windowdecor;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SPY;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
@@ -81,6 +82,7 @@
private final InputChannel mInputChannel;
private final TaskResizeInputEventReceiver mInputEventReceiver;
+ private final Context mContext;
private final SurfaceControl mInputSinkSurface;
private final IBinder mSinkClientToken;
private final InputChannel mSinkInputChannel;
@@ -97,6 +99,7 @@
Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
DisplayController displayController) {
+ mContext = context;
mSurfaceControlTransactionSupplier = surfaceControlTransactionSupplier;
mDisplayId = displayId;
mDecorationSurface = decorationSurface;
@@ -110,7 +113,7 @@
mDecorationSurface,
mClientToken,
null /* hostInputToken */,
- FLAG_NOT_FOCUSABLE,
+ FLAG_NOT_FOCUSABLE | FLAG_SPLIT_TOUCH,
PRIVATE_FLAG_TRUSTED_OVERLAY,
INPUT_FEATURE_SPY,
TYPE_APPLICATION,
@@ -180,7 +183,7 @@
mTouchRegion.setEmpty();
// Apply the geometry to the touch region.
- geometry.union(mTouchRegion);
+ geometry.union(mContext, mTouchRegion);
mInputEventReceiver.setGeometry(geometry);
mInputEventReceiver.setTouchRegion(mTouchRegion);
@@ -354,7 +357,7 @@
*/
@NonNull Region getCornersRegion() {
Region region = new Region();
- mDragResizeWindowGeometry.union(region);
+ mDragResizeWindowGeometry.union(mContext, region);
return region;
}
@@ -395,7 +398,7 @@
// Touch events are tracked in four corners. Other events are tracked in resize edges.
switch (e.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
- mShouldHandleEvents = mDragResizeWindowGeometry.shouldHandleEvent(e,
+ mShouldHandleEvents = mDragResizeWindowGeometry.shouldHandleEvent(mContext, e,
new Point() /* offset */);
if (mShouldHandleEvents) {
// Save the id of the pointer for this drag interaction; we will use the
@@ -405,8 +408,9 @@
float y = e.getY(0);
float rawX = e.getRawX(0);
float rawY = e.getRawY(0);
- final int ctrlType = mDragResizeWindowGeometry.calculateCtrlType(
- isEventFromTouchscreen(e), isEdgeResizePermitted(e), x, y);
+ final int ctrlType = mDragResizeWindowGeometry.calculateCtrlType(mContext,
+ isEventFromTouchscreen(e), isEdgeResizePermitted(mContext, e), x,
+ y);
ProtoLog.d(WM_SHELL_DESKTOP_MODE,
"%s: Handling action down, update ctrlType to %d", TAG, ctrlType);
mDragStartTaskBounds = mCallback.onDragPositioningStart(ctrlType,
@@ -496,7 +500,7 @@
// Since we are handling cursor, we know that this is not a touchscreen event, and
// that edge resizing should always be allowed.
@DragPositioningCallback.CtrlType int ctrlType =
- mDragResizeWindowGeometry.calculateCtrlType(/* isTouchscreen= */
+ mDragResizeWindowGeometry.calculateCtrlType(mContext, /* isTouchscreen= */
false, /* isEdgeResizePermitted= */ true, x, y);
int cursorType = PointerIcon.TYPE_DEFAULT;
@@ -537,7 +541,7 @@
}
private boolean shouldHandleEvent(MotionEvent e, Point offset) {
- return mDragResizeWindowGeometry.shouldHandleEvent(e, offset);
+ return mDragResizeWindowGeometry.shouldHandleEvent(mContext, e, offset);
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java
index ba5f079..014d61d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java
@@ -18,7 +18,7 @@
import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
-import static com.android.window.flags.Flags.enableWindowingEdgeDragResize;
+import static com.android.wm.shell.shared.desktopmode.DesktopModeFlags.EDGE_DRAG_RESIZE;
import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_BOTTOM;
import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_LEFT;
import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_RIGHT;
@@ -26,6 +26,7 @@
import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_UNDEFINED;
import android.annotation.NonNull;
+import android.content.Context;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
@@ -69,8 +70,8 @@
/**
* Returns the resource value to use for the resize handle on the edge of the window.
*/
- static int getResizeEdgeHandleSize(@NonNull Resources res) {
- return enableWindowingEdgeDragResize()
+ static int getResizeEdgeHandleSize(@NonNull Context context, @NonNull Resources res) {
+ return EDGE_DRAG_RESIZE.isEnabled(context)
? res.getDimensionPixelSize(R.dimen.desktop_mode_edge_handle)
: res.getDimensionPixelSize(R.dimen.freeform_resize_handle);
}
@@ -103,11 +104,11 @@
* Returns the union of all regions that can be touched for drag resizing; the corners window
* and window edges.
*/
- void union(@NonNull Region region) {
+ void union(@NonNull Context context, @NonNull Region region) {
// Apply the edge resize regions.
mTaskEdges.union(region);
- if (enableWindowingEdgeDragResize()) {
+ if (EDGE_DRAG_RESIZE.isEnabled(context)) {
// Apply the corners as well for the larger corners, to ensure we capture all possible
// touches.
mLargeTaskCorners.union(region);
@@ -120,11 +121,12 @@
/**
* Returns if this MotionEvent should be handled, based on its source and position.
*/
- boolean shouldHandleEvent(@NonNull MotionEvent e, @NonNull Point offset) {
+ boolean shouldHandleEvent(@NonNull Context context, @NonNull MotionEvent e,
+ @NonNull Point offset) {
final float x = e.getX(0) + offset.x;
final float y = e.getY(0) + offset.y;
- if (enableWindowingEdgeDragResize()) {
+ if (EDGE_DRAG_RESIZE.isEnabled(context)) {
// First check if touch falls within a corner.
// Large corner bounds are used for course input like touch, otherwise fine bounds.
boolean result = isEventFromTouchscreen(e)
@@ -132,7 +134,7 @@
: isInCornerBounds(mFineTaskCorners, x, y);
// Check if touch falls within the edge resize handle. Limit edge resizing to stylus and
// mouse input.
- if (!result && isEdgeResizePermitted(e)) {
+ if (!result && isEdgeResizePermitted(context, e)) {
result = isInEdgeResizeBounds(x, y);
}
return result;
@@ -148,8 +150,8 @@
return (e.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN;
}
- static boolean isEdgeResizePermitted(@NonNull MotionEvent e) {
- if (enableWindowingEdgeDragResize()) {
+ static boolean isEdgeResizePermitted(@NonNull Context context, @NonNull MotionEvent e) {
+ if (EDGE_DRAG_RESIZE.isEnabled(context)) {
return e.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS
|| e.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE;
} else {
@@ -174,8 +176,9 @@
* resize region.
*/
@DragPositioningCallback.CtrlType
- int calculateCtrlType(boolean isTouchscreen, boolean isEdgeResizePermitted, float x, float y) {
- if (enableWindowingEdgeDragResize()) {
+ int calculateCtrlType(@NonNull Context context, boolean isTouchscreen,
+ boolean isEdgeResizePermitted, float x, float y) {
+ if (EDGE_DRAG_RESIZE.isEnabled(context)) {
// First check if touch falls within a corner.
// Large corner bounds are used for course input like touch, otherwise fine bounds.
int ctrlType = isTouchscreen
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java
index 76096b0..e2d42b2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java
@@ -152,11 +152,8 @@
}
mDragResizeEndTransition = mTransitions.startTransition(TRANSIT_CHANGE, wct, this);
} else if (mCtrlType == CTRL_TYPE_UNDEFINED) {
- final WindowContainerTransaction wct = new WindowContainerTransaction();
DragPositioningCallbackUtility.updateTaskBounds(mRepositionTaskBounds,
mTaskBoundsAtDragStart, mRepositionStartPoint, x, y);
- wct.setBounds(mWindowDecoration.mTaskInfo.token, mRepositionTaskBounds);
- mTransitions.startTransition(TRANSIT_CHANGE, wct, this);
}
mTaskBoundsAtDragStart.setEmpty();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
index 7a81d4c..c16c16f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
@@ -17,7 +17,8 @@
import android.annotation.ColorInt
import android.annotation.DimenRes
-import android.app.ActivityManager
+import android.annotation.SuppressLint
+import android.app.ActivityManager.RunningTaskInfo
import android.content.Context
import android.content.res.ColorStateList
import android.content.res.Resources
@@ -28,7 +29,9 @@
import android.graphics.PointF
import android.graphics.Rect
import android.net.Uri
+import android.view.LayoutInflater
import android.view.MotionEvent
+import android.view.MotionEvent.ACTION_OUTSIDE
import android.view.SurfaceControl
import android.view.View
import android.view.WindowManager
@@ -42,7 +45,6 @@
import androidx.core.view.isGone
import com.android.window.flags.Flags
import com.android.wm.shell.R
-import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.split.SplitScreenConstants
import com.android.wm.shell.splitscreen.SplitScreenController
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer
@@ -63,21 +65,18 @@
class HandleMenu(
private val parentDecor: DesktopModeWindowDecoration,
private val layoutResId: Int,
- private val onClickListener: View.OnClickListener?,
- private val onTouchListener: View.OnTouchListener?,
private val appIconBitmap: Bitmap?,
private val appName: CharSequence?,
- private val displayController: DisplayController,
private val splitScreenController: SplitScreenController,
private val shouldShowWindowingPill: Boolean,
- val openInBrowserLink: Uri?,
+ private val shouldShowNewWindowButton: Boolean,
+ private val openInBrowserLink: Uri?,
private val captionWidth: Int,
private val captionHeight: Int,
captionX: Int
) {
private val context: Context = parentDecor.mDecorWindowContext
- private val taskInfo: ActivityManager.RunningTaskInfo = parentDecor.mTaskInfo
- private val decorThemeUtil = DecorThemeUtil(context)
+ private val taskInfo: RunningTaskInfo = parentDecor.mTaskInfo
private val isViewAboveStatusBar: Boolean
get() = (Flags.enableAdditionalWindowsAboveStatusBar() && !taskInfo.isFreeform)
@@ -93,10 +92,9 @@
private val marginMenuStart = loadDimensionPixelSize(
R.dimen.desktop_mode_handle_menu_margin_start)
- private var handleMenuAnimator: HandleMenuAnimator? = null
-
@VisibleForTesting
var handleMenuViewContainer: AdditionalViewContainer? = null
+ private var handleMenuView: HandleMenuView? = null
// Position of the handle menu used for laying out the handle view.
@VisibleForTesting
@@ -115,157 +113,89 @@
updateHandleMenuPillPositions(captionX)
}
- fun show() {
+ fun show(
+ onToDesktopClickListener: () -> Unit,
+ onToFullscreenClickListener: () -> Unit,
+ onToSplitScreenClickListener: () -> Unit,
+ onNewWindowClickListener: () -> Unit,
+ openInBrowserClickListener: (Uri) -> Unit,
+ onCloseMenuClickListener: () -> Unit,
+ onOutsideTouchListener: () -> Unit,
+ ) {
val ssg = SurfaceSyncGroup(TAG)
val t = SurfaceControl.Transaction()
- createHandleMenuViewContainer(t, ssg)
+ createHandleMenu(
+ t = t,
+ ssg = ssg,
+ onToDesktopClickListener = onToDesktopClickListener,
+ onToFullscreenClickListener = onToFullscreenClickListener,
+ onToSplitScreenClickListener = onToSplitScreenClickListener,
+ onNewWindowClickListener = onNewWindowClickListener,
+ openInBrowserClickListener = openInBrowserClickListener,
+ onCloseMenuClickListener = onCloseMenuClickListener,
+ onOutsideTouchListener = onOutsideTouchListener,
+ )
ssg.addTransaction(t)
ssg.markSyncReady()
- setupHandleMenu()
- animateHandleMenu()
+
+ handleMenuView?.animateOpenMenu()
}
- private fun createHandleMenuViewContainer(
+ private fun createHandleMenu(
t: SurfaceControl.Transaction,
- ssg: SurfaceSyncGroup
+ ssg: SurfaceSyncGroup,
+ onToDesktopClickListener: () -> Unit,
+ onToFullscreenClickListener: () -> Unit,
+ onToSplitScreenClickListener: () -> Unit,
+ onNewWindowClickListener: () -> Unit,
+ openInBrowserClickListener: (Uri) -> Unit,
+ onCloseMenuClickListener: () -> Unit,
+ onOutsideTouchListener: () -> Unit
) {
+ val handleMenuView = HandleMenuView(
+ context = context,
+ menuWidth = menuWidth,
+ captionHeight = captionHeight,
+ shouldShowWindowingPill = shouldShowWindowingPill,
+ shouldShowBrowserPill = shouldShowBrowserPill,
+ shouldShowNewWindowButton = shouldShowNewWindowButton
+ ).apply {
+ bind(taskInfo, appIconBitmap, appName)
+ this.onToDesktopClickListener = onToDesktopClickListener
+ this.onToFullscreenClickListener = onToFullscreenClickListener
+ this.onToSplitScreenClickListener = onToSplitScreenClickListener
+ this.onNewWindowClickListener = onNewWindowClickListener
+ this.onOpenInBrowserClickListener = {
+ openInBrowserClickListener.invoke(openInBrowserLink!!)
+ }
+ this.onCloseMenuClickListener = onCloseMenuClickListener
+ this.onOutsideTouchListener = onOutsideTouchListener
+ }
+
val x = handleMenuPosition.x.toInt()
val y = handleMenuPosition.y.toInt()
handleMenuViewContainer =
if (!taskInfo.isFreeform && Flags.enableAdditionalWindowsAboveStatusBar()) {
AdditionalSystemViewContainer(
context = context,
- layoutId = R.layout.desktop_mode_window_decor_handle_menu,
taskId = taskInfo.taskId,
x = x,
y = y,
width = menuWidth,
height = menuHeight,
flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
- WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+ WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH or
+ WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+ view = handleMenuView.rootView
)
} else {
parentDecor.addWindow(
- R.layout.desktop_mode_window_decor_handle_menu, "Handle Menu",
- t, ssg, x, y, menuWidth, menuHeight
+ handleMenuView.rootView, "Handle Menu", t, ssg, x, y, menuWidth, menuHeight
)
}
- handleMenuViewContainer?.view?.let { view ->
- handleMenuAnimator =
- HandleMenuAnimator(view, menuWidth, captionHeight.toFloat())
- }
- }
- /**
- * Animates the appearance of the handle menu and its three pills.
- */
- private fun animateHandleMenu() {
- when {
- taskInfo.isFullscreen || taskInfo.isMultiWindow -> {
- handleMenuAnimator?.animateCaptionHandleExpandToOpen()
- }
- else -> {
- handleMenuAnimator?.animateOpen()
- }
- }
- }
-
- /**
- * Set up all three pills of the handle menu: app info pill, windowing pill, & more actions
- * pill.
- */
- private fun setupHandleMenu() {
- val handleMenu = handleMenuViewContainer?.view ?: return
- handleMenu.setOnTouchListener(onTouchListener)
-
- val style = calculateMenuStyle()
- setupAppInfoPill(handleMenu, style)
- if (shouldShowWindowingPill) {
- setupWindowingPill(handleMenu, style)
- }
- setupMoreActionsPill(handleMenu, style)
- setupOpenInBrowserPill(handleMenu, style)
- }
-
- /**
- * Set up interactive elements of handle menu's app info pill.
- */
- private fun setupAppInfoPill(handleMenu: View, style: MenuStyle) {
- val pill = handleMenu.requireViewById<View>(R.id.app_info_pill).apply {
- background.colorFilter = BlendModeColorFilter(style.backgroundColor, BlendMode.MULTIPLY)
- }
-
- pill.requireViewById<HandleMenuImageButton>(R.id.collapse_menu_button)
- .let { collapseBtn ->
- collapseBtn.imageTintList = ColorStateList.valueOf(style.textColor)
- collapseBtn.setOnClickListener(onClickListener)
- collapseBtn.taskInfo = taskInfo
- }
- pill.requireViewById<ImageView>(R.id.application_icon).let { appIcon ->
- appIcon.setImageBitmap(appIconBitmap)
- }
- pill.requireViewById<TextView>(R.id.application_name).let { appNameView ->
- appNameView.text = appName
- appNameView.setTextColor(style.textColor)
- }
- }
-
- /**
- * Set up interactive elements and color of handle menu's windowing pill.
- */
- private fun setupWindowingPill(handleMenu: View, style: MenuStyle) {
- val pill = handleMenu.requireViewById<View>(R.id.windowing_pill).apply {
- background.colorFilter = BlendModeColorFilter(style.backgroundColor, BlendMode.MULTIPLY)
- }
-
- val fullscreenBtn = pill.requireViewById<ImageButton>(R.id.fullscreen_button)
- val splitscreenBtn = pill.requireViewById<ImageButton>(R.id.split_screen_button)
- val floatingBtn = pill.requireViewById<ImageButton>(R.id.floating_button)
- // TODO: Remove once implemented.
- floatingBtn.visibility = View.GONE
- val desktopBtn = handleMenu.requireViewById<ImageButton>(R.id.desktop_button)
-
- fullscreenBtn.setOnClickListener(onClickListener)
- splitscreenBtn.setOnClickListener(onClickListener)
- floatingBtn.setOnClickListener(onClickListener)
- desktopBtn.setOnClickListener(onClickListener)
-
- fullscreenBtn.isSelected = taskInfo.isFullscreen
- fullscreenBtn.imageTintList = style.windowingButtonColor
- splitscreenBtn.isSelected = taskInfo.isMultiWindow
- splitscreenBtn.imageTintList = style.windowingButtonColor
- floatingBtn.isSelected = taskInfo.isPinned
- floatingBtn.imageTintList = style.windowingButtonColor
- desktopBtn.isSelected = taskInfo.isFreeform
- desktopBtn.imageTintList = style.windowingButtonColor
- }
-
- /**
- * Set up interactive elements & height of handle menu's more actions pill
- */
- private fun setupMoreActionsPill(handleMenu: View, style: MenuStyle) {
- val pill = handleMenu.requireViewById<View>(R.id.more_actions_pill).apply {
- isGone = !SHOULD_SHOW_MORE_ACTIONS_PILL
- background.colorFilter = BlendModeColorFilter(style.backgroundColor, BlendMode.MULTIPLY)
- }
- pill.requireViewById<Button>(R.id.screenshot_button).let { screenshotBtn ->
- screenshotBtn.setTextColor(style.textColor)
- screenshotBtn.compoundDrawableTintList = ColorStateList.valueOf(style.textColor)
- }
- }
-
- private fun setupOpenInBrowserPill(handleMenu: View, style: MenuStyle) {
- val pill = handleMenu.requireViewById<View>(R.id.open_in_browser_pill).apply {
- isGone = !shouldShowBrowserPill
- background.colorFilter = BlendModeColorFilter(style.backgroundColor, BlendMode.MULTIPLY)
- }
-
- pill.requireViewById<Button>(R.id.open_in_browser_button).let { browserButton ->
- browserButton.setOnClickListener(onClickListener)
- browserButton.setTextColor(style.textColor)
- browserButton.compoundDrawableTintList = ColorStateList.valueOf(style.textColor)
- }
+ this.handleMenuView = handleMenuView
}
/**
@@ -359,16 +289,8 @@
fun checkMotionEvent(ev: MotionEvent) {
// If the menu view is above status bar, we can let the views handle input directly.
if (isViewAboveStatusBar) return
- val handleMenu = handleMenuViewContainer?.view ?: return
- val collapse = handleMenu.findViewById<HandleMenuImageButton>(R.id.collapse_menu_button)
val inputPoint = translateInputToLocalSpace(ev)
- val inputInCollapseButton = pointInView(collapse, inputPoint.x, inputPoint.y)
- val action = ev.actionMasked
- collapse.isHovered = inputInCollapseButton && action != MotionEvent.ACTION_UP
- collapse.isPressed = inputInCollapseButton && action == MotionEvent.ACTION_DOWN
- if (action == MotionEvent.ACTION_UP && inputInCollapseButton) {
- collapse.performClick()
- }
+ handleMenuView?.checkMotionEvent(ev, inputPoint)
}
// Translate the input point from display coordinates to the same space as the handle menu.
@@ -439,9 +361,17 @@
R.dimen.desktop_mode_handle_menu_windowing_pill_height)
menuHeight -= pillTopMargin
}
- if (!SHOULD_SHOW_MORE_ACTIONS_PILL) {
+ if (!SHOULD_SHOW_SCREENSHOT_BUTTON) {
menuHeight -= loadDimensionPixelSize(
- R.dimen.desktop_mode_handle_menu_more_actions_pill_height)
+ R.dimen.desktop_mode_handle_menu_screenshot_height
+ )
+ }
+ if (!shouldShowNewWindowButton) {
+ menuHeight -= loadDimensionPixelSize(
+ R.dimen.desktop_mode_handle_menu_new_window_height
+ )
+ }
+ if (!SHOULD_SHOW_SCREENSHOT_BUTTON && !shouldShowNewWindowButton) {
menuHeight -= pillTopMargin
}
if (!shouldShowBrowserPill) {
@@ -460,48 +390,244 @@
}
fun close() {
- val after = {
+ handleMenuView?.animateCloseMenu {
handleMenuViewContainer?.releaseView()
handleMenuViewContainer = null
}
- if (taskInfo.isFullscreen || taskInfo.isMultiWindow) {
- handleMenuAnimator?.animateCollapseIntoHandleClose(after)
- } else {
- handleMenuAnimator?.animateClose(after)
- }
}
- private fun calculateMenuStyle(): MenuStyle {
- val colorScheme = decorThemeUtil.getColorScheme(taskInfo)
- return MenuStyle(
- backgroundColor = colorScheme.surfaceBright.toArgb(),
- textColor = colorScheme.onSurface.toArgb(),
- windowingButtonColor = ColorStateList(
- arrayOf(
- intArrayOf(android.R.attr.state_pressed),
- intArrayOf(android.R.attr.state_focused),
- intArrayOf(android.R.attr.state_selected),
- intArrayOf(),
+ /** The view within the Handle Menu, with options to change the windowing mode and more. */
+ @SuppressLint("ClickableViewAccessibility")
+ class HandleMenuView(
+ context: Context,
+ menuWidth: Int,
+ captionHeight: Int,
+ private val shouldShowWindowingPill: Boolean,
+ private val shouldShowBrowserPill: Boolean,
+ private val shouldShowNewWindowButton: Boolean
+ ) {
+ val rootView = LayoutInflater.from(context)
+ .inflate(R.layout.desktop_mode_window_decor_handle_menu, null /* root */) as View
+
+ // App Info Pill.
+ private val appInfoPill = rootView.requireViewById<View>(R.id.app_info_pill)
+ private val collapseMenuButton = appInfoPill.requireViewById<HandleMenuImageButton>(
+ R.id.collapse_menu_button)
+ private val appIconView = appInfoPill.requireViewById<ImageView>(R.id.application_icon)
+ private val appNameView = appInfoPill.requireViewById<TextView>(R.id.application_name)
+
+ // Windowing Pill.
+ private val windowingPill = rootView.requireViewById<View>(R.id.windowing_pill)
+ private val fullscreenBtn = windowingPill.requireViewById<ImageButton>(
+ R.id.fullscreen_button)
+ private val splitscreenBtn = windowingPill.requireViewById<ImageButton>(
+ R.id.split_screen_button)
+ private val floatingBtn = windowingPill.requireViewById<ImageButton>(R.id.floating_button)
+ private val desktopBtn = windowingPill.requireViewById<ImageButton>(R.id.desktop_button)
+
+ // More Actions Pill.
+ private val moreActionsPill = rootView.requireViewById<View>(R.id.more_actions_pill)
+ private val screenshotBtn = moreActionsPill.requireViewById<Button>(R.id.screenshot_button)
+ private val newWindowBtn = moreActionsPill.requireViewById<Button>(R.id.new_window_button)
+
+ // Open in Browser Pill.
+ private val openInBrowserPill = rootView.requireViewById<View>(R.id.open_in_browser_pill)
+ private val browserBtn = openInBrowserPill.requireViewById<Button>(
+ R.id.open_in_browser_button)
+
+ private val decorThemeUtil = DecorThemeUtil(context)
+ private val animator = HandleMenuAnimator(rootView, menuWidth, captionHeight.toFloat())
+
+ private lateinit var taskInfo: RunningTaskInfo
+ private lateinit var style: MenuStyle
+
+ var onToDesktopClickListener: (() -> Unit)? = null
+ var onToFullscreenClickListener: (() -> Unit)? = null
+ var onToSplitScreenClickListener: (() -> Unit)? = null
+ var onNewWindowClickListener: (() -> Unit)? = null
+ var onOpenInBrowserClickListener: (() -> Unit)? = null
+ var onCloseMenuClickListener: (() -> Unit)? = null
+ var onOutsideTouchListener: (() -> Unit)? = null
+
+ init {
+ fullscreenBtn.setOnClickListener { onToFullscreenClickListener?.invoke() }
+ splitscreenBtn.setOnClickListener { onToSplitScreenClickListener?.invoke() }
+ desktopBtn.setOnClickListener { onToDesktopClickListener?.invoke() }
+ browserBtn.setOnClickListener { onOpenInBrowserClickListener?.invoke() }
+ collapseMenuButton.setOnClickListener { onCloseMenuClickListener?.invoke() }
+ newWindowBtn.setOnClickListener { onNewWindowClickListener?.invoke() }
+
+ rootView.setOnTouchListener { _, event ->
+ if (event.actionMasked == ACTION_OUTSIDE) {
+ onOutsideTouchListener?.invoke()
+ return@setOnTouchListener false
+ }
+ return@setOnTouchListener true
+ }
+ }
+
+ /** Binds the menu views to the new data. */
+ fun bind(taskInfo: RunningTaskInfo, appIconBitmap: Bitmap?, appName: CharSequence?) {
+ this.taskInfo = taskInfo
+ this.style = calculateMenuStyle(taskInfo)
+
+ bindAppInfoPill(style, appIconBitmap, appName)
+ if (shouldShowWindowingPill) {
+ bindWindowingPill(style)
+ }
+ bindMoreActionsPill(style)
+ bindOpenInBrowserPill(style)
+ }
+
+ /** Animates the menu opening. */
+ fun animateOpenMenu() {
+ if (taskInfo.isFullscreen || taskInfo.isMultiWindow) {
+ animator.animateCaptionHandleExpandToOpen()
+ } else {
+ animator.animateOpen()
+ }
+ }
+
+ /** Animates the menu closing. */
+ fun animateCloseMenu(onAnimFinish: () -> Unit) {
+ if (taskInfo.isFullscreen || taskInfo.isMultiWindow) {
+ animator.animateCollapseIntoHandleClose(onAnimFinish)
+ } else {
+ animator.animateClose(onAnimFinish)
+ }
+ }
+
+ /**
+ * Checks whether a motion event falls inside this menu, and invokes a click of the
+ * collapse button if needed.
+ * Note: should only be called when regular click detection doesn't work because input is
+ * detected through the status bar layer with a global input monitor.
+ */
+ fun checkMotionEvent(ev: MotionEvent, inputPointLocal: PointF) {
+ val inputInCollapseButton = pointInView(
+ collapseMenuButton,
+ inputPointLocal.x,
+ inputPointLocal.y
+ )
+ val action = ev.actionMasked
+ collapseMenuButton.isHovered = inputInCollapseButton
+ && action != MotionEvent.ACTION_UP
+ collapseMenuButton.isPressed = inputInCollapseButton
+ && action == MotionEvent.ACTION_DOWN
+ if (action == MotionEvent.ACTION_UP && inputInCollapseButton) {
+ collapseMenuButton.performClick()
+ }
+ }
+
+ private fun pointInView(v: View?, x: Float, y: Float): Boolean {
+ return v != null && v.left <= x && v.right >= x && v.top <= y && v.bottom >= y
+ }
+
+ private fun calculateMenuStyle(taskInfo: RunningTaskInfo): MenuStyle {
+ val colorScheme = decorThemeUtil.getColorScheme(taskInfo)
+ return MenuStyle(
+ backgroundColor = colorScheme.surfaceBright.toArgb(),
+ textColor = colorScheme.onSurface.toArgb(),
+ windowingButtonColor = ColorStateList(
+ arrayOf(
+ intArrayOf(android.R.attr.state_pressed),
+ intArrayOf(android.R.attr.state_focused),
+ intArrayOf(android.R.attr.state_selected),
+ intArrayOf(),
+ ),
+ intArrayOf(
+ colorScheme.onSurface.toArgb(),
+ colorScheme.onSurface.toArgb(),
+ colorScheme.primary.toArgb(),
+ colorScheme.onSurface.toArgb(),
+ )
),
- intArrayOf(
- colorScheme.onSurface.toArgb(),
- colorScheme.onSurface.toArgb(),
- colorScheme.primary.toArgb(),
- colorScheme.onSurface.toArgb(),
+ )
+ }
+
+ private fun bindAppInfoPill(
+ style: MenuStyle,
+ appIconBitmap: Bitmap?,
+ appName: CharSequence?
+ ) {
+ appInfoPill.background.colorFilter = BlendModeColorFilter(
+ style.backgroundColor, BlendMode.MULTIPLY
+ )
+
+ collapseMenuButton.apply {
+ imageTintList = ColorStateList.valueOf(style.textColor)
+ this.taskInfo = this@HandleMenuView.taskInfo
+ }
+ appIconView.setImageBitmap(appIconBitmap)
+ appNameView.apply {
+ text = appName
+ setTextColor(style.textColor)
+ }
+ }
+
+ private fun bindWindowingPill(style: MenuStyle) {
+ windowingPill.background.colorFilter = BlendModeColorFilter(
+ style.backgroundColor, BlendMode.MULTIPLY
+ )
+
+ // TODO: Remove once implemented.
+ floatingBtn.visibility = View.GONE
+
+ fullscreenBtn.isSelected = taskInfo.isFullscreen
+ fullscreenBtn.imageTintList = style.windowingButtonColor
+ splitscreenBtn.isSelected = taskInfo.isMultiWindow
+ splitscreenBtn.imageTintList = style.windowingButtonColor
+ floatingBtn.isSelected = taskInfo.isPinned
+ floatingBtn.imageTintList = style.windowingButtonColor
+ desktopBtn.isSelected = taskInfo.isFreeform
+ desktopBtn.imageTintList = style.windowingButtonColor
+ }
+
+ private fun bindMoreActionsPill(style: MenuStyle) {
+ moreActionsPill.apply {
+ isGone = !shouldShowNewWindowButton && !SHOULD_SHOW_SCREENSHOT_BUTTON
+ }
+ screenshotBtn.apply {
+ isGone = !SHOULD_SHOW_SCREENSHOT_BUTTON
+ background.colorFilter =
+ BlendModeColorFilter(style.backgroundColor, BlendMode.MULTIPLY
)
- ),
+ setTextColor(style.textColor)
+ compoundDrawableTintList = ColorStateList.valueOf(style.textColor)
+ }
+ newWindowBtn.apply {
+ isGone = !shouldShowNewWindowButton
+ background.colorFilter =
+ BlendModeColorFilter(style.backgroundColor, BlendMode.MULTIPLY)
+ setTextColor(style.textColor)
+ compoundDrawableTintList = ColorStateList.valueOf(style.textColor)
+ }
+ }
+
+ private fun bindOpenInBrowserPill(style: MenuStyle) {
+ openInBrowserPill.apply {
+ isGone = !shouldShowBrowserPill
+ background.colorFilter = BlendModeColorFilter(
+ style.backgroundColor, BlendMode.MULTIPLY
+ )
+ }
+
+ browserBtn.apply {
+ setTextColor(style.textColor)
+ compoundDrawableTintList = ColorStateList.valueOf(style.textColor)
+ }
+ }
+
+ private data class MenuStyle(
+ @ColorInt val backgroundColor: Int,
+ @ColorInt val textColor: Int,
+ val windowingButtonColor: ColorStateList,
)
}
- private data class MenuStyle(
- @ColorInt val backgroundColor: Int,
- @ColorInt val textColor: Int,
- val windowingButtonColor: ColorStateList,
- )
-
companion object {
private const val TAG = "HandleMenu"
- private const val SHOULD_SHOW_MORE_ACTIONS_PILL = false
+ private const val SHOULD_SHOW_SCREENSHOT_BUTTON = false
}
}
@@ -510,13 +636,11 @@
fun create(
parentDecor: DesktopModeWindowDecoration,
layoutResId: Int,
- onClickListener: View.OnClickListener?,
- onTouchListener: View.OnTouchListener?,
appIconBitmap: Bitmap?,
appName: CharSequence?,
- displayController: DisplayController,
splitScreenController: SplitScreenController,
shouldShowWindowingPill: Boolean,
+ shouldShowNewWindowButton: Boolean,
openInBrowserLink: Uri?,
captionWidth: Int,
captionHeight: Int,
@@ -529,13 +653,11 @@
override fun create(
parentDecor: DesktopModeWindowDecoration,
layoutResId: Int,
- onClickListener: View.OnClickListener?,
- onTouchListener: View.OnTouchListener?,
appIconBitmap: Bitmap?,
appName: CharSequence?,
- displayController: DisplayController,
splitScreenController: SplitScreenController,
shouldShowWindowingPill: Boolean,
+ shouldShowNewWindowButton: Boolean,
openInBrowserLink: Uri?,
captionWidth: Int,
captionHeight: Int,
@@ -544,13 +666,11 @@
return HandleMenu(
parentDecor,
layoutResId,
- onClickListener,
- onTouchListener,
appIconBitmap,
appName,
- displayController,
splitScreenController,
shouldShowWindowingPill,
+ shouldShowNewWindowButton,
openInBrowserLink,
captionWidth,
captionHeight,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt
index aa2ce0f..54b33e93 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt
@@ -66,7 +66,6 @@
import com.android.wm.shell.windowdecor.common.DecorThemeUtil
import com.android.wm.shell.windowdecor.common.OPACITY_12
import com.android.wm.shell.windowdecor.common.OPACITY_40
-import com.android.wm.shell.windowdecor.common.OnTaskActionClickListener
import com.android.wm.shell.windowdecor.common.withAlpha
import java.util.function.Supplier
@@ -102,15 +101,15 @@
/** Creates and shows the maximize window. */
fun show(
- onMaximizeClickListener: OnTaskActionClickListener,
- onLeftSnapClickListener: OnTaskActionClickListener,
- onRightSnapClickListener: OnTaskActionClickListener,
+ onMaximizeOrRestoreClickListener: () -> Unit,
+ onLeftSnapClickListener: () -> Unit,
+ onRightSnapClickListener: () -> Unit,
onHoverListener: (Boolean) -> Unit,
onOutsideTouchListener: () -> Unit,
) {
if (maximizeMenu != null) return
createMaximizeMenu(
- onMaximizeClickListener = onMaximizeClickListener,
+ onMaximizeClickListener = onMaximizeOrRestoreClickListener,
onLeftSnapClickListener = onLeftSnapClickListener,
onRightSnapClickListener = onRightSnapClickListener,
onHoverListener = onHoverListener,
@@ -129,9 +128,9 @@
/** Create a maximize menu that is attached to the display area. */
private fun createMaximizeMenu(
- onMaximizeClickListener: OnTaskActionClickListener,
- onLeftSnapClickListener: OnTaskActionClickListener,
- onRightSnapClickListener: OnTaskActionClickListener,
+ onMaximizeClickListener: () -> Unit,
+ onLeftSnapClickListener: () -> Unit,
+ onRightSnapClickListener: () -> Unit,
onHoverListener: (Boolean) -> Unit,
onOutsideTouchListener: () -> Unit
) {
@@ -147,7 +146,8 @@
menuHeight,
WindowManager.LayoutParams.TYPE_APPLICATION,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
+ or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+ or WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
PixelFormat.TRANSPARENT
)
lp.title = "Maximize Menu for Task=" + taskInfo.taskId
@@ -165,17 +165,10 @@
menuHeight = menuHeight,
menuPadding = menuPadding,
).also { menuView ->
- val taskId = taskInfo.taskId
menuView.bind(taskInfo)
- menuView.onMaximizeClickListener = {
- onMaximizeClickListener.onClick(taskId, "maximize_menu_option")
- }
- menuView.onLeftSnapClickListener = {
- onLeftSnapClickListener.onClick(taskId, "left_snap_option")
- }
- menuView.onRightSnapClickListener = {
- onRightSnapClickListener.onClick(taskId, "right_snap_option")
- }
+ menuView.onMaximizeClickListener = onMaximizeClickListener
+ menuView.onLeftSnapClickListener = onLeftSnapClickListener
+ menuView.onRightSnapClickListener = onRightSnapClickListener
menuView.onMenuHoverListener = onHoverListener
menuView.onOutsideTouchListener = onOutsideTouchListener
viewHost.setView(menuView.rootView, lp)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/OnTaskRepositionAnimationListener.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/OnTaskRepositionAnimationListener.kt
new file mode 100644
index 0000000..214a6fa
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/OnTaskRepositionAnimationListener.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.wm.shell.windowdecor
+
+/**
+ * Listener that allows notifies when an animation that is repositioning a task is starting
+ * and finishing the animation.
+ */
+interface OnTaskRepositionAnimationListener {
+ /**
+ * Notifies that an animation is about to be started.
+ */
+ fun onAnimationStart(taskId: Int)
+
+ /**
+ * Notifies that an animation is about to be finished.
+ */
+ fun onAnimationEnd(taskId: Int)
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.kt
index cd2dac8..fd6c4d8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.kt
@@ -32,6 +32,7 @@
import android.view.SurfaceControlViewHost
import android.view.SurfaceSession
import android.view.WindowManager
+import android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL
import android.view.WindowlessWindowManager
import android.widget.ImageView
import android.window.TaskConstants
@@ -151,6 +152,7 @@
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSPARENT)
lp.title = "Resize veil icon window of Task=" + taskInfo.taskId
+ lp.inputFeatures = INPUT_FEATURE_NO_INPUT_CHANNEL
lp.setTrustedOverlay()
val wwm = WindowlessWindowManager(taskInfo.configuration,
iconSurface, null /* hostInputToken */)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java
index b5b476d..7f2c1a8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java
@@ -163,14 +163,7 @@
} else {
DragPositioningCallbackUtility.updateTaskBounds(mRepositionTaskBounds,
mTaskBoundsAtDragStart, mRepositionStartPoint, x, y);
- if (!mTaskBoundsAtDragStart.equals(mRepositionTaskBounds)) {
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- wct.setBounds(mDesktopWindowDecoration.mTaskInfo.token, mRepositionTaskBounds);
- mTransitions.startTransition(TRANSIT_CHANGE, wct, this);
- } else {
- // Drag-move ended where it originally started, no need to update WM.
- mInteractionJankMonitor.end(CUJ_DESKTOP_MODE_DRAG_WINDOW);
- }
+ mInteractionJankMonitor.end(CUJ_DESKTOP_MODE_DRAG_WINDOW);
}
mCtrlType = CTRL_TYPE_UNDEFINED;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 3b8657d4..0c58987 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -22,6 +22,8 @@
import static android.view.WindowInsets.Type.captionBar;
import static android.view.WindowInsets.Type.mandatorySystemGestures;
import static android.view.WindowInsets.Type.statusBars;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -106,6 +108,7 @@
* System-wide context. Only used to create context with overridden configurations.
*/
final Context mContext;
+ final @NonNull Context mUserContext;
final @NonNull DisplayController mDisplayController;
final ShellTaskOrganizer mTaskOrganizer;
final Supplier<SurfaceControl.Builder> mSurfaceControlBuilderSupplier;
@@ -147,11 +150,12 @@
WindowDecoration(
Context context,
+ @NonNull Context userContext,
DisplayController displayController,
ShellTaskOrganizer taskOrganizer,
RunningTaskInfo taskInfo,
SurfaceControl taskSurface) {
- this(context, displayController, taskOrganizer, taskInfo, taskSurface,
+ this(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface,
SurfaceControl.Builder::new, SurfaceControl.Transaction::new,
WindowContainerTransaction::new, SurfaceControl::new,
new SurfaceControlViewHostFactory() {});
@@ -159,6 +163,7 @@
WindowDecoration(
Context context,
+ @NonNull Context userContext,
@NonNull DisplayController displayController,
ShellTaskOrganizer taskOrganizer,
RunningTaskInfo taskInfo,
@@ -169,6 +174,7 @@
Supplier<SurfaceControl> surfaceControlSupplier,
SurfaceControlViewHostFactory surfaceControlViewHostFactory) {
mContext = context;
+ mUserContext = userContext;
mDisplayController = displayController;
mTaskOrganizer = taskOrganizer;
mTaskInfo = taskInfo;
@@ -177,7 +183,6 @@
mSurfaceControlTransactionSupplier = surfaceControlTransactionSupplier;
mWindowContainerTransactionSupplier = windowContainerTransactionSupplier;
mSurfaceControlViewHostFactory = surfaceControlViewHostFactory;
-
mDisplay = mDisplayController.getDisplay(mTaskInfo.displayId);
}
@@ -236,7 +241,8 @@
outResult.mHeight = taskBounds.height();
outResult.mRootView.setTaskFocusState(mTaskInfo.isFocused);
final Resources resources = mDecorWindowContext.getResources();
- outResult.mCaptionHeight = loadDimensionPixelSize(resources, params.mCaptionHeightId);
+ outResult.mCaptionHeight = loadDimensionPixelSize(resources, params.mCaptionHeightId)
+ + params.mCaptionTopPadding;
outResult.mCaptionWidth = params.mCaptionWidthId != Resources.ID_NULL
? loadDimensionPixelSize(resources, params.mCaptionWidthId) : taskBounds.width();
outResult.mCaptionX = (outResult.mWidth - outResult.mCaptionWidth) / 2;
@@ -440,9 +446,12 @@
}
mCaptionWindowManager.setConfiguration(mTaskInfo.getConfiguration());
final WindowManager.LayoutParams lp =
- new WindowManager.LayoutParams(outResult.mCaptionWidth, outResult.mCaptionHeight,
+ new WindowManager.LayoutParams(
+ outResult.mCaptionWidth,
+ outResult.mCaptionHeight,
TYPE_APPLICATION,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT);
+ FLAG_NOT_FOCUSABLE | FLAG_SPLIT_TOUCH,
+ PixelFormat.TRANSPARENT);
lp.setTitle("Caption of Task=" + mTaskInfo.taskId);
lp.setTrustedOverlay();
lp.inputFeatures = params.mInputFeatures;
@@ -456,6 +465,7 @@
}
mViewHost.getRootSurfaceControl().applyTransactionOnDraw(onDrawTransaction);
}
+ outResult.mRootView.setPadding(0, params.mCaptionTopPadding, 0, 0);
mViewHost.setView(outResult.mRootView, lp);
Trace.endSection();
} else {
@@ -466,6 +476,7 @@
}
mViewHost.getRootSurfaceControl().applyTransactionOnDraw(onDrawTransaction);
}
+ outResult.mRootView.setPadding(0, params.mCaptionTopPadding, 0, 0);
mViewHost.relayout(lp);
Trace.endSection();
}
@@ -610,6 +621,49 @@
* Create a window associated with this WindowDecoration.
* Note that subclass must dispose of this when the task is hidden/closed.
*
+ * @param v View to attach to the window
+ * @param t the transaction to apply
+ * @param xPos x position of new window
+ * @param yPos y position of new window
+ * @param width width of new window
+ * @param height height of new window
+ * @return the {@link AdditionalViewHostViewContainer} that was added.
+ */
+ AdditionalViewHostViewContainer addWindow(@NonNull View v, @NonNull String namePrefix,
+ @NonNull SurfaceControl.Transaction t, @NonNull SurfaceSyncGroup ssg,
+ int xPos, int yPos, int width, int height) {
+ final SurfaceControl.Builder builder = mSurfaceControlBuilderSupplier.get();
+ SurfaceControl windowSurfaceControl = builder
+ .setName(namePrefix + " of Task=" + mTaskInfo.taskId)
+ .setContainerLayer()
+ .setParent(mDecorationContainerSurface)
+ .setCallsite("WindowDecoration.addWindow")
+ .build();
+ t.setPosition(windowSurfaceControl, xPos, yPos)
+ .setWindowCrop(windowSurfaceControl, width, height)
+ .show(windowSurfaceControl);
+ final WindowManager.LayoutParams lp =
+ new WindowManager.LayoutParams(
+ width,
+ height,
+ TYPE_APPLICATION,
+ FLAG_NOT_FOCUSABLE | FLAG_WATCH_OUTSIDE_TOUCH | FLAG_SPLIT_TOUCH,
+ PixelFormat.TRANSPARENT);
+ lp.setTitle("Additional window of Task=" + mTaskInfo.taskId);
+ lp.setTrustedOverlay();
+ WindowlessWindowManager windowManager = new WindowlessWindowManager(mTaskInfo.configuration,
+ windowSurfaceControl, null /* hostInputToken */);
+ SurfaceControlViewHost viewHost = mSurfaceControlViewHostFactory
+ .create(mDecorWindowContext, mDisplay, windowManager);
+ ssg.add(viewHost.getSurfacePackage(), () -> viewHost.setView(v, lp));
+ return new AdditionalViewHostViewContainer(windowSurfaceControl, viewHost,
+ mSurfaceControlTransactionSupplier);
+ }
+
+ /**
+ * Create a window associated with this WindowDecoration.
+ * Note that subclass must dispose of this when the task is hidden/closed.
+ *
* @param layoutId layout to make the window from
* @param t the transaction to apply
* @param xPos x position of new window
@@ -621,32 +675,8 @@
AdditionalViewHostViewContainer addWindow(int layoutId, String namePrefix,
SurfaceControl.Transaction t, SurfaceSyncGroup ssg, int xPos, int yPos,
int width, int height) {
- final SurfaceControl.Builder builder = mSurfaceControlBuilderSupplier.get();
- SurfaceControl windowSurfaceControl = builder
- .setName(namePrefix + " of Task=" + mTaskInfo.taskId)
- .setContainerLayer()
- .setParent(mDecorationContainerSurface)
- .setCallsite("WindowDecoration.addWindow")
- .build();
- View v = LayoutInflater.from(mDecorWindowContext).inflate(layoutId, null);
-
- t.setPosition(windowSurfaceControl, xPos, yPos)
- .setWindowCrop(windowSurfaceControl, width, height)
- .show(windowSurfaceControl);
- final WindowManager.LayoutParams lp =
- new WindowManager.LayoutParams(width, height, TYPE_APPLICATION,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | FLAG_WATCH_OUTSIDE_TOUCH,
- PixelFormat.TRANSPARENT);
- lp.setTitle("Additional window of Task=" + mTaskInfo.taskId);
- lp.setTrustedOverlay();
- WindowlessWindowManager windowManager = new WindowlessWindowManager(mTaskInfo.configuration,
- windowSurfaceControl, null /* hostInputToken */);
- SurfaceControlViewHost viewHost = mSurfaceControlViewHostFactory
- .create(mDecorWindowContext, mDisplay, windowManager);
- ssg.add(viewHost.getSurfacePackage(), () -> viewHost.setView(v, lp));
- return new AdditionalViewHostViewContainer(windowSurfaceControl, viewHost,
- mSurfaceControlTransactionSupplier);
+ final View v = LayoutInflater.from(mDecorWindowContext).inflate(layoutId, null);
+ return addWindow(v, namePrefix, t, ssg, xPos, yPos, width, height);
}
/**
@@ -680,6 +710,8 @@
int mShadowRadiusId;
int mCornerRadius;
+ int mCaptionTopPadding;
+
Configuration mWindowDecorConfig;
boolean mApplyStartTransactionOnDraw;
@@ -696,6 +728,8 @@
mShadowRadiusId = Resources.ID_NULL;
mCornerRadius = 0;
+ mCaptionTopPadding = 0;
+
mApplyStartTransactionOnDraw = false;
mSetTaskPositionAndCrop = false;
mWindowDecorConfig = null;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainer.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainer.kt
index f1370bb..cadd80e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainer.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainer.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.windowdecor.additionalviewcontainer
+import android.annotation.LayoutRes
import android.content.Context
import android.graphics.PixelFormat
import android.view.Gravity
@@ -29,24 +30,52 @@
* for view containers that should be above the status bar layer.
*/
class AdditionalSystemViewContainer(
- private val context: Context,
+ context: Context,
taskId: Int,
x: Int,
y: Int,
width: Int,
height: Int,
flags: Int,
- layoutId: Int? = null
-) : AdditionalViewContainer() {
override val view: View
+) : AdditionalViewContainer() {
+
+ constructor(
+ context: Context,
+ taskId: Int,
+ x: Int,
+ y: Int,
+ width: Int,
+ height: Int,
+ flags: Int,
+ @LayoutRes layoutId: Int
+ ) : this(
+ context = context,
+ taskId = taskId,
+ x = x,
+ y = y,
+ width = width,
+ height = height,
+ flags = flags,
+ view = LayoutInflater.from(context).inflate(layoutId, null /* parent */)
+ )
+
+ constructor(
+ context: Context, taskId: Int, x: Int, y: Int, width: Int, height: Int, flags: Int
+ ) : this(
+ context = context,
+ taskId = taskId,
+ x = x,
+ y = y,
+ width = width,
+ height = height,
+ flags = flags,
+ view = View(context)
+ )
+
val windowManager: WindowManager? = context.getSystemService(WindowManager::class.java)
init {
- if (layoutId != null) {
- view = LayoutInflater.from(context).inflate(layoutId, null)
- } else {
- view = View(context)
- }
val lp = WindowManager.LayoutParams(
width, height, x, y,
WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt
index 17b3dea..d0eb6da 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt
@@ -238,12 +238,12 @@
override fun onHandleMenuClosed() {}
- fun setAnimatingTaskResize(animatingTaskResize: Boolean) {
- // If animating a task resize, cancel any running hover animations
- if (animatingTaskResize) {
+ fun setAnimatingTaskResizeOrReposition(animatingTaskResizeOrReposition: Boolean) {
+ // If animating a task resize or reposition, cancel any running hover animations
+ if (animatingTaskResizeOrReposition) {
maximizeButtonView.cancelHoverAnimation()
}
- maximizeButtonView.hoverDisabled = animatingTaskResize
+ maximizeButtonView.hoverDisabled = animatingTaskResizeOrReposition
}
fun onMaximizeWindowHoverExit() {
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/CloseAllAppsWithAppHeaderExitTest.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/CloseAllAppsWithAppHeaderExitTest.kt
new file mode 100644
index 0000000..9ba3a45
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/CloseAllAppsWithAppHeaderExitTest.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.service.desktopmode.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.flicker.service.desktopmode.scenarios.CloseAllAppsWithAppHeaderExit
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/** Functional test for [CloseAllAppsWithAppHeaderExit]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+open class CloseAllAppsWithAppHeaderExitTest : CloseAllAppsWithAppHeaderExit() {
+
+ @Test
+ override fun closeAllAppsInDesktop() {
+ super.closeAllAppsInDesktop()
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/DragAppWindowMultiWindowTest.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/DragAppWindowMultiWindowTest.kt
new file mode 100644
index 0000000..ed1d488
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/DragAppWindowMultiWindowTest.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.service.desktopmode.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.flicker.service.desktopmode.scenarios.DragAppWindowMultiWindow
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/** Functional test for [DragAppWindowMultiWindow]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+open class DragAppWindowMultiWindowTest : DragAppWindowMultiWindow()
+{
+ @Test
+ override fun dragAppWindow() {
+ super.dragAppWindow()
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/DragAppWindowSingleWindowTest.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/DragAppWindowSingleWindowTest.kt
new file mode 100644
index 0000000..d8b9348
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/DragAppWindowSingleWindowTest.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.service.desktopmode.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.flicker.service.desktopmode.scenarios.DragAppWindowSingleWindow
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/** Functional test for [DragAppWindowSingleWindow]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+open class DragAppWindowSingleWindowTest : DragAppWindowSingleWindow()
+{
+ @Test
+ override fun dragAppWindow() {
+ super.dragAppWindow()
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/EnterDesktopWithAppHandleMenuTest.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/EnterDesktopWithAppHandleMenuTest.kt
new file mode 100644
index 0000000..546ce2d
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/EnterDesktopWithAppHandleMenuTest.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.service.desktopmode.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.flicker.service.desktopmode.scenarios.EnterDesktopWithAppHandleMenu
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/** Functional test for [EnterDesktopWithAppHandleMenu]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+open class EnterDesktopWithAppHandleMenuTest : EnterDesktopWithAppHandleMenu() {
+ @Test
+ override fun enterDesktopWithAppHandleMenu() {
+ super.enterDesktopWithAppHandleMenu()
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/EnterDesktopWithDragTest.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/EnterDesktopWithDragTest.kt
new file mode 100644
index 0000000..b5fdb16
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/EnterDesktopWithDragTest.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.service.desktopmode.functional
+
+import android.platform.test.annotations.Postsubmit
+import android.tools.Rotation
+import com.android.wm.shell.flicker.service.desktopmode.scenarios.EnterDesktopWithDrag
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/** Functional test for [EnterDesktopWithDrag]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+open class EnterDesktopWithDragTest : EnterDesktopWithDrag(Rotation.ROTATION_0) {
+
+ @Test
+ override fun enterDesktopWithDrag() {
+ super.enterDesktopWithDrag()
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/ExitDesktopWithDragToTopDragZoneTest.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/ExitDesktopWithDragToTopDragZoneTest.kt
new file mode 100644
index 0000000..8f802d2
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/ExitDesktopWithDragToTopDragZoneTest.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.service.desktopmode.functional
+
+import android.platform.test.annotations.Postsubmit
+import android.tools.Rotation
+import com.android.wm.shell.flicker.service.desktopmode.scenarios.ExitDesktopWithDragToTopDragZone
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/** Functional test for [ExitDesktopWithDragToTopDragZone]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+open class ExitDesktopWithDragToTopDragZoneTest :
+ ExitDesktopWithDragToTopDragZone(Rotation.ROTATION_0) {
+ @Test
+ override fun exitDesktopWithDragToTopDragZone() {
+ super.exitDesktopWithDragToTopDragZone()
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/MaximizeAppWindowTest.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/MaximizeAppWindowTest.kt
new file mode 100644
index 0000000..f899082
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/MaximizeAppWindowTest.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.service.desktopmode.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.flicker.service.desktopmode.scenarios.MaximizeAppWindow
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/** Functional test for [MaximizeAppWindow]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+open class MaximizeAppWindowTest : MaximizeAppWindow()
+{
+ @Test
+ override fun maximizeAppWindow() {
+ super.maximizeAppWindow()
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/MinimizeWindowOnAppOpenTest.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/MinimizeWindowOnAppOpenTest.kt
new file mode 100644
index 0000000..63c428a
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/MinimizeWindowOnAppOpenTest.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.service.desktopmode.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.flicker.service.desktopmode.scenarios.MinimizeWindowOnAppOpen
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/** Functional test for [MinimizeWindowOnAppOpen]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+open class MinimizeWindowOnAppOpenTest : MinimizeWindowOnAppOpen()
+{
+ @Test
+ override fun openAppToMinimizeWindow() {
+ // Launch a new app while 4 apps are already open on desktop. This should result in the
+ // first app we opened to be minimized.
+ super.openAppToMinimizeWindow()
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/ResizeAppWithCornerResizeTest.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/ResizeAppWithCornerResizeTest.kt
new file mode 100644
index 0000000..4797aaf
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/ResizeAppWithCornerResizeTest.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.service.desktopmode.functional
+
+import android.platform.test.annotations.Postsubmit
+import android.tools.Rotation
+import com.android.wm.shell.flicker.service.desktopmode.scenarios.ResizeAppWithCornerResize
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/** Functional test for [ResizeAppWithCornerResize]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+open class ResizeAppWithCornerResizeTest : ResizeAppWithCornerResize(Rotation.ROTATION_0) {
+ @Test
+ override fun resizeAppWithCornerResize() {
+ super.resizeAppWithCornerResize()
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/SwitchToOverviewFromDesktopTest.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/SwitchToOverviewFromDesktopTest.kt
new file mode 100644
index 0000000..9a71361
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/functional/SwitchToOverviewFromDesktopTest.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.service.desktopmode.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.flicker.service.desktopmode.scenarios.SwitchToOverviewFromDesktop
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/** Functional test for [SwitchToOverviewFromDesktop]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+open class SwitchToOverviewFromDesktopTest : SwitchToOverviewFromDesktop() {
+ @Test
+ override fun switchToOverview() {
+ super.switchToOverview()
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
index e91828b..716a148 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
@@ -16,10 +16,6 @@
package com.android.wm.shell;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
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;
@@ -443,84 +439,6 @@
}
@Test
- public void testOnCameraCompatActivityChanged() {
- final RunningTaskInfo taskInfo1 = createTaskInfo(/* taskId= */ 1,
- WINDOWING_MODE_FULLSCREEN);
- taskInfo1.displayId = DEFAULT_DISPLAY;
- taskInfo1.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState =
- CAMERA_COMPAT_CONTROL_HIDDEN;
- final TrackingTaskListener taskListener = new TrackingTaskListener();
- mOrganizer.addListenerForType(taskListener, TASK_LISTENER_TYPE_FULLSCREEN);
- mOrganizer.onTaskAppeared(taskInfo1, /* leash= */ null);
-
- // Task listener sent to compat UI is null if top activity doesn't request a camera
- // compat control.
- verifyOnCompatInfoChangedInvokedWith(taskInfo1, null /* taskListener */);
-
- // Task listener is non-null when request a camera compat control for a visible task.
- clearInvocations(mCompatUI);
- final RunningTaskInfo taskInfo2 =
- createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode());
- taskInfo2.displayId = taskInfo1.displayId;
- taskInfo2.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState =
- CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
- taskInfo2.isVisible = true;
- mOrganizer.onTaskInfoChanged(taskInfo2);
- verifyOnCompatInfoChangedInvokedWith(taskInfo2, taskListener);
-
- // CompatUIController#onCompatInfoChanged is called when requested state for a camera
- // compat control changes for a visible task.
- clearInvocations(mCompatUI);
- final RunningTaskInfo taskInfo3 =
- createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode());
- taskInfo3.displayId = taskInfo1.displayId;
- taskInfo3.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState =
- CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
- taskInfo3.isVisible = true;
- mOrganizer.onTaskInfoChanged(taskInfo3);
- verifyOnCompatInfoChangedInvokedWith(taskInfo3, taskListener);
-
- // CompatUIController#onCompatInfoChanged is called when a top activity goes in size compat
- // mode for a visible task that has a compat control.
- clearInvocations(mCompatUI);
- final RunningTaskInfo taskInfo4 =
- createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode());
- taskInfo4.displayId = taskInfo1.displayId;
- taskInfo4.appCompatTaskInfo.topActivityInSizeCompat = true;
- taskInfo4.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState =
- CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
- taskInfo4.isVisible = true;
- mOrganizer.onTaskInfoChanged(taskInfo4);
- verifyOnCompatInfoChangedInvokedWith(taskInfo4, taskListener);
-
- // Task linster is null when a camera compat control is dimissed for a visible task.
- clearInvocations(mCompatUI);
- final RunningTaskInfo taskInfo5 =
- createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode());
- taskInfo5.displayId = taskInfo1.displayId;
- taskInfo5.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState =
- CAMERA_COMPAT_CONTROL_DISMISSED;
- taskInfo5.isVisible = true;
- mOrganizer.onTaskInfoChanged(taskInfo5);
- verifyOnCompatInfoChangedInvokedWith(taskInfo5, null /* taskListener */);
-
- // Task linster is null when request a camera compat control for a invisible task.
- clearInvocations(mCompatUI);
- final RunningTaskInfo taskInfo6 =
- createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode());
- taskInfo6.displayId = taskInfo1.displayId;
- taskInfo6.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState =
- CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
- taskInfo6.isVisible = false;
- mOrganizer.onTaskInfoChanged(taskInfo6);
- verifyOnCompatInfoChangedInvokedWith(taskInfo6, null /* taskListener */);
-
- clearInvocations(mCompatUI);
- mOrganizer.onTaskVanished(taskInfo1);
- verifyOnCompatInfoChangedInvokedWith(taskInfo1, null /* taskListener */);
- }
-
- @Test
public void testAddLocusListener() {
RunningTaskInfo task1 = createTaskInfo(/* taskId= */ 1, WINDOWING_MODE_MULTI_WINDOW);
task1.isVisible = true;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
index 57e469d..56fad95 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
@@ -68,6 +68,7 @@
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.sysui.ShellSharedConstants;
+import com.android.wm.shell.transition.Transitions;
import org.junit.Before;
import org.junit.Test;
@@ -114,6 +115,8 @@
@Mock
private ShellCommandHandler mShellCommandHandler;
@Mock
+ private Transitions mTransitions;
+ @Mock
private RootTaskDisplayAreaOrganizer mRootTaskDisplayAreaOrganizer;
private BackAnimationController mController;
@@ -156,7 +159,8 @@
mContentResolver,
mAnimationBackground,
mShellBackAnimationRegistry,
- mShellCommandHandler);
+ mShellCommandHandler,
+ mTransitions);
mShellInit.init();
mShellExecutor.flushAll();
mTouchableRegion = new Rect(0, 0, 100, 100);
@@ -316,7 +320,8 @@
mContentResolver,
mAnimationBackground,
mShellBackAnimationRegistry,
- mShellCommandHandler);
+ mShellCommandHandler,
+ mTransitions);
shellInit.init();
registerAnimation(BackNavigationInfo.TYPE_RETURN_TO_HOME);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
index fc7a777..77e22cd 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
@@ -16,8 +16,6 @@
package com.android.wm.shell.compatui;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
import static android.view.WindowInsets.Type.navigationBars;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
@@ -34,7 +32,6 @@
import static org.mockito.Mockito.verify;
import android.app.ActivityManager.RunningTaskInfo;
-import android.app.CameraCompatTaskInfo.CameraCompatControlState;
import android.app.TaskInfo;
import android.content.Context;
import android.content.res.Configuration;
@@ -199,8 +196,7 @@
@Test
@RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
public void testOnCompatInfoChanged() {
- TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true,
- CAMERA_COMPAT_CONTROL_HIDDEN);
+ TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
// Verify that the compat controls are added with non-null task listener.
mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
@@ -214,8 +210,7 @@
// Verify that the compat controls and letterbox education are updated with new size compat
// info.
clearInvocations(mMockCompatLayout, mMockLetterboxEduLayout, mController);
- taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true,
- CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED);
+ taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
verify(mMockCompatLayout).updateCompatInfo(taskInfo, mMockTaskListener,
@@ -228,7 +223,7 @@
// Verify that compat controls and letterbox education are removed with null task listener.
clearInvocations(mMockCompatLayout, mMockLetterboxEduLayout, mController);
mController.onCompatInfoChanged(new CompatUIInfo(createTaskInfo(DISPLAY_ID, TASK_ID,
- /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN),
+ /* hasSizeCompat= */ true),
/* taskListener= */ null));
verify(mMockCompatLayout).release();
@@ -243,8 +238,7 @@
doReturn(false).when(mMockLetterboxEduLayout).createLayout(anyBoolean());
doReturn(false).when(mMockRestartDialogLayout).createLayout(anyBoolean());
- TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true,
- CAMERA_COMPAT_CONTROL_HIDDEN);
+ TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
verify(mController).createCompatUiWindowManager(any(), eq(taskInfo), eq(mMockTaskListener));
@@ -274,8 +268,7 @@
doReturn(false).when(mMockLetterboxEduLayout).updateCompatInfo(any(), any(), anyBoolean());
doReturn(false).when(mMockRestartDialogLayout).updateCompatInfo(any(), any(), anyBoolean());
- TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true,
- CAMERA_COMPAT_CONTROL_HIDDEN);
+ TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
verify(mController).createCompatUiWindowManager(any(), eq(taskInfo), eq(mMockTaskListener));
@@ -326,7 +319,7 @@
public void testOnDisplayRemoved() {
mController.onDisplayAdded(DISPLAY_ID);
mController.onCompatInfoChanged(new CompatUIInfo(createTaskInfo(DISPLAY_ID, TASK_ID,
- /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener));
+ /* hasSizeCompat= */ true), mMockTaskListener));
mController.onDisplayRemoved(DISPLAY_ID + 1);
@@ -348,7 +341,7 @@
@RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
public void testOnDisplayConfigurationChanged() {
mController.onCompatInfoChanged(new CompatUIInfo(createTaskInfo(DISPLAY_ID, TASK_ID,
- /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener));
+ /* hasSizeCompat= */ true), mMockTaskListener));
mController.onDisplayConfigurationChanged(DISPLAY_ID + 1, new Configuration());
@@ -368,7 +361,7 @@
public void testInsetsChanged() {
mController.onDisplayAdded(DISPLAY_ID);
mController.onCompatInfoChanged(new CompatUIInfo(createTaskInfo(DISPLAY_ID, TASK_ID,
- /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener));
+ /* hasSizeCompat= */ true), mMockTaskListener));
InsetsState insetsState = new InsetsState();
InsetsSource insetsSource = new InsetsSource(
InsetsSource.createId(null, 0, navigationBars()), navigationBars());
@@ -395,7 +388,7 @@
@RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
public void testChangeLayoutsVisibilityOnImeShowHide() {
mController.onCompatInfoChanged(new CompatUIInfo(createTaskInfo(DISPLAY_ID, TASK_ID,
- /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener));
+ /* hasSizeCompat= */ true), mMockTaskListener));
// Verify that the restart button is hidden after IME is showing.
mController.onImeVisibilityChanged(DISPLAY_ID, /* isShowing= */ true);
@@ -405,8 +398,7 @@
verify(mMockRestartDialogLayout).updateVisibility(false);
// Verify button remains hidden while IME is showing.
- TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true,
- CAMERA_COMPAT_CONTROL_HIDDEN);
+ TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
verify(mMockCompatLayout).updateCompatInfo(taskInfo, mMockTaskListener,
@@ -428,7 +420,7 @@
@RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
public void testChangeLayoutsVisibilityOnKeyguardShowingChanged() {
mController.onCompatInfoChanged(new CompatUIInfo(createTaskInfo(DISPLAY_ID, TASK_ID,
- /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener));
+ /* hasSizeCompat= */ true), mMockTaskListener));
// Verify that the restart button is hidden after keyguard becomes showing.
mController.onKeyguardVisibilityChanged(true, false, false);
@@ -438,8 +430,7 @@
verify(mMockRestartDialogLayout).updateVisibility(false);
// Verify button remains hidden while keyguard is showing.
- TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true,
- CAMERA_COMPAT_CONTROL_HIDDEN);
+ TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
verify(mMockCompatLayout).updateCompatInfo(taskInfo, mMockTaskListener,
@@ -461,7 +452,7 @@
@RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
public void testLayoutsRemainHiddenOnKeyguardShowingFalseWhenImeIsShowing() {
mController.onCompatInfoChanged(new CompatUIInfo(createTaskInfo(DISPLAY_ID, TASK_ID,
- /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener));
+ /* hasSizeCompat= */ true), mMockTaskListener));
mController.onImeVisibilityChanged(DISPLAY_ID, /* isShowing= */ true);
mController.onKeyguardVisibilityChanged(true, false, false);
@@ -491,7 +482,7 @@
@RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
public void testLayoutsRemainHiddenOnImeHideWhenKeyguardIsShowing() {
mController.onCompatInfoChanged(new CompatUIInfo(createTaskInfo(DISPLAY_ID, TASK_ID,
- /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener));
+ /* hasSizeCompat= */ true), mMockTaskListener));
mController.onImeVisibilityChanged(DISPLAY_ID, /* isShowing= */ true);
mController.onKeyguardVisibilityChanged(true, false, false);
@@ -520,8 +511,7 @@
@Test
@RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
public void testRestartLayoutRecreatedIfNeeded() {
- final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID,
- /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN);
+ final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
doReturn(true).when(mMockRestartDialogLayout)
.needsToBeRecreated(any(TaskInfo.class),
any(ShellTaskOrganizer.TaskListener.class));
@@ -536,8 +526,7 @@
@Test
@RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
public void testRestartLayoutNotRecreatedIfNotNeeded() {
- final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID,
- /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN);
+ final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
doReturn(false).when(mMockRestartDialogLayout)
.needsToBeRecreated(any(TaskInfo.class),
any(ShellTaskOrganizer.TaskListener.class));
@@ -557,9 +546,8 @@
Assert.assertTrue(mController.hasShownUserAspectRatioSettingsButton());
// Create new task
- final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID,
- /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN, /* isVisible */ true,
- /* isFocused */ true);
+ final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true,
+ /* isVisible */ true, /* isFocused */ true);
// Simulate new task being shown
mController.updateActiveTaskInfo(taskInfo);
@@ -574,9 +562,8 @@
@RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
public void testUpdateActiveTaskInfo_newTask_notVisibleOrFocused_notUpdated() {
// Create new task
- final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID,
- /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN, /* isVisible */ true,
- /* isFocused */ true);
+ final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true,
+ /* isVisible */ true, /* isFocused */ true);
// Simulate task being shown
mController.updateActiveTaskInfo(taskInfo);
@@ -593,9 +580,8 @@
final int newTaskId = TASK_ID + 1;
// Create visible but NOT focused task
- final TaskInfo taskInfo1 = createTaskInfo(DISPLAY_ID, newTaskId,
- /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN, /* isVisible */ true,
- /* isFocused */ false);
+ final TaskInfo taskInfo1 = createTaskInfo(DISPLAY_ID, newTaskId, /* hasSizeCompat= */ true,
+ /* isVisible */ true, /* isFocused */ false);
// Simulate new task being shown
mController.updateActiveTaskInfo(taskInfo1);
@@ -606,9 +592,8 @@
Assert.assertTrue(mController.hasShownUserAspectRatioSettingsButton());
// Create focused but NOT visible task
- final TaskInfo taskInfo2 = createTaskInfo(DISPLAY_ID, newTaskId,
- /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN, /* isVisible */ false,
- /* isFocused */ true);
+ final TaskInfo taskInfo2 = createTaskInfo(DISPLAY_ID, newTaskId, /* hasSizeCompat= */ true,
+ /* isVisible */ false, /* isFocused */ true);
// Simulate new task being shown
mController.updateActiveTaskInfo(taskInfo2);
@@ -619,9 +604,8 @@
Assert.assertTrue(mController.hasShownUserAspectRatioSettingsButton());
// Create NOT focused but NOT visible task
- final TaskInfo taskInfo3 = createTaskInfo(DISPLAY_ID, newTaskId,
- /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN, /* isVisible */ false,
- /* isFocused */ false);
+ final TaskInfo taskInfo3 = createTaskInfo(DISPLAY_ID, newTaskId, /* hasSizeCompat= */ true,
+ /* isVisible */ false, /* isFocused */ false);
// Simulate new task being shown
mController.updateActiveTaskInfo(taskInfo3);
@@ -636,9 +620,8 @@
@RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
public void testUpdateActiveTaskInfo_sameTask_notUpdated() {
// Create new task
- final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID,
- /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN, /* isVisible */ true,
- /* isFocused */ true);
+ final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true,
+ /* isVisible */ true, /* isFocused */ true);
// Simulate new task being shown
mController.updateActiveTaskInfo(taskInfo);
@@ -665,9 +648,8 @@
@RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
public void testUpdateActiveTaskInfo_transparentTask_notUpdated() {
// Create new task
- final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID,
- /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN, /* isVisible */ true,
- /* isFocused */ true);
+ final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true,
+ /* isVisible */ true, /* isFocused */ true);
// Simulate new task being shown
mController.updateActiveTaskInfo(taskInfo);
@@ -684,9 +666,8 @@
final int newTaskId = TASK_ID + 1;
// Create transparent task
- final TaskInfo taskInfo1 = createTaskInfo(DISPLAY_ID, newTaskId,
- /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN, /* isVisible */ true,
- /* isFocused */ true, /* isTopActivityTransparent */ true);
+ final TaskInfo taskInfo1 = createTaskInfo(DISPLAY_ID, newTaskId, /* hasSizeCompat= */ true,
+ /* isVisible */ true, /* isFocused */ true, /* isTopActivityTransparent */ true);
// Simulate new task being shown
mController.updateActiveTaskInfo(taskInfo1);
@@ -699,8 +680,7 @@
@Test
public void testLetterboxEduLayout_notCreatedWhenLetterboxEducationIsDisabled() {
- TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true,
- CAMERA_COMPAT_CONTROL_HIDDEN);
+ TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
taskInfo.appCompatTaskInfo.isLetterboxEducationEnabled = false;
mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
@@ -709,29 +689,23 @@
eq(mMockTaskListener));
}
- private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat,
- @CameraCompatControlState int cameraCompatControlState) {
- return createTaskInfo(displayId, taskId, hasSizeCompat, cameraCompatControlState,
- /* isVisible */ false, /* isFocused */ false,
- /* isTopActivityTransparent */ false);
+ private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat) {
+ return createTaskInfo(displayId, taskId, hasSizeCompat, /* isVisible */ false,
+ /* isFocused */ false, /* isTopActivityTransparent */ false);
}
private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat,
- @CameraCompatControlState int cameraCompatControlState, boolean isVisible,
- boolean isFocused) {
- return createTaskInfo(displayId, taskId, hasSizeCompat, cameraCompatControlState,
+ boolean isVisible, boolean isFocused) {
+ return createTaskInfo(displayId, taskId, hasSizeCompat,
isVisible, isFocused, /* isTopActivityTransparent */ false);
}
private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat,
- @CameraCompatControlState int cameraCompatControlState, boolean isVisible,
- boolean isFocused, boolean isTopActivityTransparent) {
+ boolean isVisible, boolean isFocused, boolean isTopActivityTransparent) {
RunningTaskInfo taskInfo = new RunningTaskInfo();
taskInfo.taskId = taskId;
taskInfo.displayId = displayId;
taskInfo.appCompatTaskInfo.topActivityInSizeCompat = hasSizeCompat;
- taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState =
- cameraCompatControlState;
taskInfo.isVisible = isVisible;
taskInfo.isFocused = isFocused;
taskInfo.isTopActivityTransparent = isTopActivityTransparent;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUILayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUILayoutTest.java
index 33d69f5..3b93861 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUILayoutTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUILayoutTest.java
@@ -16,20 +16,13 @@
package com.android.wm.shell.compatui;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
-
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
-import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
import android.app.ActivityManager;
-import android.app.CameraCompatTaskInfo.CameraCompatControlState;
import android.app.TaskInfo;
import android.graphics.Rect;
import android.platform.test.annotations.RequiresFlagsDisabled;
@@ -52,7 +45,6 @@
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.compatui.CompatUIController.CompatUIHintsState;
import com.android.wm.shell.compatui.api.CompatUIEvent;
-import com.android.wm.shell.compatui.impl.CompatUIEvents;
import junit.framework.Assert;
@@ -97,7 +89,7 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
doReturn(100).when(mCompatUIConfiguration).getHideSizeCompatRestartButtonTolerance();
- mTaskInfo = createTaskInfo(/* hasSizeCompat= */ false, CAMERA_COMPAT_CONTROL_HIDDEN);
+ mTaskInfo = createTaskInfo(/* hasSizeCompat= */ false);
mWindowManager = new CompatUIWindowManager(mContext, mTaskInfo, mSyncTransactionQueue,
mCallback, mTaskListener, new DisplayLayout(), new CompatUIHintsState(),
mCompatUIConfiguration, mOnRestartButtonClicked);
@@ -151,113 +143,13 @@
verify(mLayout).setSizeCompatHintVisibility(/* show= */ false);
}
- @Test
- @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
- public void testUpdateCameraTreatmentButton_treatmentAppliedByDefault() {
- mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
- mWindowManager.createLayout(/* canShow= */ true);
- final ImageButton button =
- mLayout.findViewById(R.id.camera_compat_treatment_button);
- button.performClick();
-
- verify(mWindowManager).onCameraTreatmentButtonClicked();
- verifyOnCameraControlStateUpdatedInvokedWith(TASK_ID,
- CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED);
-
- button.performClick();
-
- verifyOnCameraControlStateUpdatedInvokedWith(TASK_ID,
- CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED);
- }
-
- @Test
- @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
- public void testUpdateCameraTreatmentButton_treatmentSuggestedByDefault() {
- mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
- mWindowManager.createLayout(/* canShow= */ true);
- final ImageButton button =
- mLayout.findViewById(R.id.camera_compat_treatment_button);
- button.performClick();
-
- verify(mWindowManager).onCameraTreatmentButtonClicked();
- verifyOnCameraControlStateUpdatedInvokedWith(TASK_ID,
- CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED);
-
- button.performClick();
-
- verifyOnCameraControlStateUpdatedInvokedWith(TASK_ID,
- CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED);
- }
-
- @Test
- @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
- public void testOnCameraDismissButtonClicked() {
- mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
- mWindowManager.createLayout(/* canShow= */ true);
- final ImageButton button =
- mLayout.findViewById(R.id.camera_compat_dismiss_button);
- button.performClick();
-
- verify(mWindowManager).onCameraDismissButtonClicked();
- verifyOnCameraControlStateUpdatedInvokedWith(TASK_ID, CAMERA_COMPAT_CONTROL_DISMISSED);
- verify(mLayout).setCameraControlVisibility(/* show */ false);
- }
-
- @Test
- @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
- public void testOnLongClickForCameraTreatmentButton() {
- doNothing().when(mWindowManager).onCameraButtonLongClicked();
-
- final ImageButton button =
- mLayout.findViewById(R.id.camera_compat_treatment_button);
- button.performLongClick();
-
- verify(mWindowManager).onCameraButtonLongClicked();
- }
-
- @Test
- @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
- public void testOnLongClickForCameraDismissButton() {
- doNothing().when(mWindowManager).onCameraButtonLongClicked();
-
- final ImageButton button = mLayout.findViewById(R.id.camera_compat_dismiss_button);
- button.performLongClick();
-
- verify(mWindowManager).onCameraButtonLongClicked();
- }
-
- @Test
- @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
- public void testOnClickForCameraCompatHint() {
- mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
- mWindowManager.createLayout(/* canShow= */ true);
- final LinearLayout hint = mLayout.findViewById(R.id.camera_compat_hint);
- hint.performClick();
-
- verify(mLayout).setCameraCompatHintVisibility(/* show= */ false);
- }
-
- private static TaskInfo createTaskInfo(boolean hasSizeCompat,
- @CameraCompatControlState int cameraCompatControlState) {
+ private static TaskInfo createTaskInfo(boolean hasSizeCompat) {
ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
taskInfo.taskId = TASK_ID;
taskInfo.appCompatTaskInfo.topActivityInSizeCompat = hasSizeCompat;
- taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState =
- cameraCompatControlState;
taskInfo.appCompatTaskInfo.topActivityLetterboxHeight = 1000;
taskInfo.appCompatTaskInfo.topActivityLetterboxWidth = 1000;
taskInfo.configuration.windowConfiguration.setBounds(new Rect(0, 0, 2000, 2000));
return taskInfo;
}
-
- private void verifyOnCameraControlStateUpdatedInvokedWith(int taskId, int state) {
- final ArgumentCaptor<CompatUIEvent> captureValue = ArgumentCaptor.forClass(
- CompatUIEvent.class);
- verify(mCallback).accept(captureValue.capture());
- final CompatUIEvents.CameraControlStateUpdated compatUIEvent =
- (CompatUIEvents.CameraControlStateUpdated) captureValue.getValue();
- Assert.assertEquals((compatUIEvent).getTaskId(), taskId);
- Assert.assertEquals((compatUIEvent).getState(), state);
- clearInvocations(mCallback);
- }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java
index eb3da8f..c5033f3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java
@@ -16,10 +16,6 @@
package com.android.wm.shell.compatui;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT;
import static android.view.WindowInsets.Type.navigationBars;
import static android.view.WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
@@ -36,10 +32,10 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.app.ActivityManager;
-import android.app.CameraCompatTaskInfo;
import android.app.TaskInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -65,7 +61,6 @@
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.compatui.CompatUIController.CompatUIHintsState;
import com.android.wm.shell.compatui.api.CompatUIEvent;
-import com.android.wm.shell.compatui.impl.CompatUIEvents;
import junit.framework.Assert;
@@ -115,7 +110,7 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
doReturn(100).when(mCompatUIConfiguration).getHideSizeCompatRestartButtonTolerance();
- mTaskInfo = createTaskInfo(/* hasSizeCompat= */ false, CAMERA_COMPAT_CONTROL_HIDDEN);
+ mTaskInfo = createTaskInfo(/* hasSizeCompat= */ false);
final DisplayInfo displayInfo = new DisplayInfo();
displayInfo.logicalWidth = TASK_WIDTH;
@@ -186,45 +181,6 @@
@Test
@RequiresFlagsDisabled(FLAG_APP_COMPAT_UI_FRAMEWORK)
- public void testCreateCameraCompatControl() {
- // Doesn't create layout if show is false.
- mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
- assertTrue(mWindowManager.createLayout(/* canShow= */ false));
-
- verify(mWindowManager, never()).inflateLayout();
-
- // Doesn't create hint popup.
- mWindowManager.mCompatUIHintsState.mHasShownCameraCompatHint = true;
- assertTrue(mWindowManager.createLayout(/* canShow= */ true));
-
- verify(mWindowManager).inflateLayout();
- verify(mLayout).setCameraControlVisibility(/* show= */ true);
- verify(mLayout, never()).setCameraCompatHintVisibility(/* show= */ true);
-
- // Creates hint popup.
- clearInvocations(mWindowManager);
- clearInvocations(mLayout);
- mWindowManager.release();
- mWindowManager.mCompatUIHintsState.mHasShownCameraCompatHint = false;
- assertTrue(mWindowManager.createLayout(/* canShow= */ true));
-
- verify(mWindowManager).inflateLayout();
- assertNotNull(mLayout);
- verify(mLayout).setCameraControlVisibility(/* show= */ true);
- verify(mLayout).setCameraCompatHintVisibility(/* show= */ true);
- assertTrue(mWindowManager.mCompatUIHintsState.mHasShownCameraCompatHint);
-
- // Returns false and doesn't create layout if Camera Compat state is hidden
- clearInvocations(mWindowManager);
- mWindowManager.release();
- mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN;
- assertFalse(mWindowManager.createLayout(/* canShow= */ true));
-
- verify(mWindowManager, never()).inflateLayout();
- }
-
- @Test
- @RequiresFlagsDisabled(FLAG_APP_COMPAT_UI_FRAMEWORK)
public void testRelease() {
mWindowManager.mHasSizeCompat = true;
mWindowManager.createLayout(/* canShow= */ true);
@@ -241,10 +197,11 @@
public void testUpdateCompatInfo() {
mWindowManager.mHasSizeCompat = true;
mWindowManager.createLayout(/* canShow= */ true);
+ verify(mLayout).setRestartButtonVisibility(/* show= */ true);
// No diff
clearInvocations(mWindowManager);
- TaskInfo taskInfo = createTaskInfo(/* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN);
+ TaskInfo taskInfo = createTaskInfo(/* hasSizeCompat= */ true);
doReturn(true).when(mWindowManager).shouldShowSizeCompatRestartButton(any());
assertTrue(mWindowManager.updateCompatInfo(taskInfo, mTaskListener, /* canShow= */ true));
@@ -261,58 +218,25 @@
verify(mWindowManager).release();
verify(mWindowManager).createLayout(/* canShow= */ true);
- // Change Camera Compat state, show a control.
+ // Change has Size Compat to false, no more CompatIU.
clearInvocations(mWindowManager);
clearInvocations(mLayout);
- taskInfo = createTaskInfo(/* hasSizeCompat= */ true,
- CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED);
- assertTrue(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true));
-
- verify(mLayout).setCameraControlVisibility(/* show= */ true);
- verify(mLayout).updateCameraTreatmentButton(
- CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED);
-
- // Change Camera Compat state, update a control.
- clearInvocations(mWindowManager);
- clearInvocations(mLayout);
- taskInfo = createTaskInfo(/* hasSizeCompat= */ true,
- CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED);
- assertTrue(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true));
-
- verify(mLayout).setCameraControlVisibility(/* show= */ true);
- verify(mLayout).updateCameraTreatmentButton(
- CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED);
-
- // Change has Size Compat to false, hides restart button.
- clearInvocations(mWindowManager);
- clearInvocations(mLayout);
- taskInfo = createTaskInfo(/* hasSizeCompat= */ false,
- CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED);
- assertTrue(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true));
-
- verify(mLayout).setRestartButtonVisibility(/* show= */ false);
+ taskInfo = createTaskInfo(/* hasSizeCompat= */ false);
+ assertFalse(mWindowManager.updateCompatInfo(taskInfo, newTaskListener,
+ /* canShow= */ true));
// Change has Size Compat to true, shows restart button.
clearInvocations(mWindowManager);
clearInvocations(mLayout);
- taskInfo = createTaskInfo(/* hasSizeCompat= */ true,
- CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED);
+ taskInfo = createTaskInfo(/* hasSizeCompat= */ true);
assertTrue(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true));
- verify(mLayout).setRestartButtonVisibility(/* show= */ true);
-
- // Change Camera Compat state to dismissed, hide a control.
- clearInvocations(mWindowManager);
- clearInvocations(mLayout);
- taskInfo = createTaskInfo(/* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_DISMISSED);
- assertTrue(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true));
-
- verify(mLayout).setCameraControlVisibility(/* show= */ false);
+ verify(mLayout, times(2)).setRestartButtonVisibility(/* show= */ true);
// Change task bounds, update position.
clearInvocations(mWindowManager);
clearInvocations(mLayout);
- taskInfo = createTaskInfo(/* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN);
+ taskInfo = createTaskInfo(/* hasSizeCompat= */ true);
taskInfo.configuration.windowConfiguration.setBounds(new Rect(0, 1000, 0, 2000));
assertTrue(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true));
@@ -321,7 +245,7 @@
// Change has Size Compat to false, release layout.
clearInvocations(mWindowManager);
clearInvocations(mLayout);
- taskInfo = createTaskInfo(/* hasSizeCompat= */ false, CAMERA_COMPAT_CONTROL_HIDDEN);
+ taskInfo = createTaskInfo(/* hasSizeCompat= */ false);
assertFalse(
mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true));
@@ -338,15 +262,14 @@
// Change topActivityInSizeCompat to false and pass canShow true, layout shouldn't be
// inflated
clearInvocations(mWindowManager);
- TaskInfo taskInfo = createTaskInfo(/* hasSizeCompat= */ false,
- CAMERA_COMPAT_CONTROL_HIDDEN);
+ TaskInfo taskInfo = createTaskInfo(/* hasSizeCompat= */ false);
mWindowManager.updateCompatInfo(taskInfo, mTaskListener, /* canShow= */ true);
verify(mWindowManager, never()).inflateLayout();
// Change topActivityInSizeCompat to true and pass canShow true, layout should be inflated.
clearInvocations(mWindowManager);
- taskInfo = createTaskInfo(/* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN);
+ taskInfo = createTaskInfo(/* hasSizeCompat= */ true);
mWindowManager.updateCompatInfo(taskInfo, mTaskListener, /* canShow= */ true);
verify(mWindowManager).inflateLayout();
@@ -443,37 +366,6 @@
@Test
@RequiresFlagsDisabled(FLAG_APP_COMPAT_UI_FRAMEWORK)
- public void testOnCameraDismissButtonClicked() {
- mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
- mWindowManager.createLayout(/* canShow= */ true);
- clearInvocations(mLayout);
- mWindowManager.onCameraDismissButtonClicked();
-
- verifyOnCameraControlStateUpdatedInvokedWith(TASK_ID, CAMERA_COMPAT_CONTROL_DISMISSED);
- verify(mLayout).setCameraControlVisibility(/* show= */ false);
- }
-
- @Test
- @RequiresFlagsDisabled(FLAG_APP_COMPAT_UI_FRAMEWORK)
- public void testOnCameraTreatmentButtonClicked() {
- mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
- mWindowManager.createLayout(/* canShow= */ true);
- clearInvocations(mLayout);
- mWindowManager.onCameraTreatmentButtonClicked();
-
- verifyOnCameraControlStateUpdatedInvokedWith(TASK_ID,
- CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED);
- verify(mLayout).updateCameraTreatmentButton(CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED);
-
- mWindowManager.onCameraTreatmentButtonClicked();
-
- verifyOnCameraControlStateUpdatedInvokedWith(TASK_ID,
- CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED);
- verify(mLayout).updateCameraTreatmentButton(CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED);
- }
-
- @Test
- @RequiresFlagsDisabled(FLAG_APP_COMPAT_UI_FRAMEWORK)
public void testOnRestartButtonClicked() {
mWindowManager.onRestartButtonClicked();
@@ -505,22 +397,6 @@
@Test
@RequiresFlagsDisabled(FLAG_APP_COMPAT_UI_FRAMEWORK)
- public void testOnCameraControlLongClicked_showHint() {
- // Not create hint popup.
- mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
- mWindowManager.mCompatUIHintsState.mHasShownCameraCompatHint = true;
- mWindowManager.createLayout(/* canShow= */ true);
-
- verify(mWindowManager).inflateLayout();
- verify(mLayout, never()).setCameraCompatHintVisibility(/* show= */ true);
-
- mWindowManager.onCameraButtonLongClicked();
-
- verify(mLayout).setCameraCompatHintVisibility(/* show= */ true);
- }
-
- @Test
- @RequiresFlagsDisabled(FLAG_APP_COMPAT_UI_FRAMEWORK)
public void testWhenDockedStateHasChanged_needsToBeRecreated() {
ActivityManager.RunningTaskInfo newTaskInfo = new ActivityManager.RunningTaskInfo();
newTaskInfo.configuration.uiMode |= Configuration.UI_MODE_TYPE_DESK;
@@ -538,7 +414,7 @@
mCompatUIConfiguration, mOnRestartButtonClicked);
// Simulate rotation of activity in square display
- TaskInfo taskInfo = createTaskInfo(true, CAMERA_COMPAT_CONTROL_HIDDEN);
+ TaskInfo taskInfo = createTaskInfo(true);
taskInfo.appCompatTaskInfo.topActivityLetterboxHeight = TASK_HEIGHT;
taskInfo.appCompatTaskInfo.topActivityLetterboxWidth = 1850;
@@ -567,13 +443,10 @@
assertTrue(mWindowManager.shouldShowSizeCompatRestartButton(taskInfo));
}
- private static TaskInfo createTaskInfo(boolean hasSizeCompat,
- @CameraCompatTaskInfo.CameraCompatControlState int cameraCompatControlState) {
+ private static TaskInfo createTaskInfo(boolean hasSizeCompat) {
ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
taskInfo.taskId = TASK_ID;
taskInfo.appCompatTaskInfo.topActivityInSizeCompat = hasSizeCompat;
- taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState =
- cameraCompatControlState;
taskInfo.configuration.uiMode &= ~Configuration.UI_MODE_TYPE_DESK;
// Letterboxed activity that takes half the screen should show size compat restart button
taskInfo.appCompatTaskInfo.topActivityLetterboxHeight = 1000;
@@ -582,15 +455,4 @@
taskInfo.configuration.smallestScreenWidthDp = LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
return taskInfo;
}
-
- private void verifyOnCameraControlStateUpdatedInvokedWith(int taskId, int state) {
- final ArgumentCaptor<CompatUIEvent> captureValue = ArgumentCaptor.forClass(
- CompatUIEvent.class);
- verify(mCallback).accept(captureValue.capture());
- final CompatUIEvents.CameraControlStateUpdated compatUIEvent =
- (CompatUIEvents.CameraControlStateUpdated) captureValue.getValue();
- Assert.assertEquals((compatUIEvent).getTaskId(), taskId);
- Assert.assertEquals((compatUIEvent).getState(), state);
- clearInvocations(mCallback);
- }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsLayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsLayoutTest.java
index 3fa21ce..7a64196 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsLayoutTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsLayoutTest.java
@@ -16,8 +16,6 @@
package com.android.wm.shell.compatui;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
-
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.window.flags.Flags.FLAG_APP_COMPAT_UI_FRAMEWORK;
@@ -26,7 +24,6 @@
import static org.mockito.Mockito.verify;
import android.app.ActivityManager;
-import android.app.CameraCompatTaskInfo.CameraCompatControlState;
import android.app.TaskInfo;
import android.content.ComponentName;
import android.platform.test.annotations.RequiresFlagsDisabled;
@@ -98,7 +95,7 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mTaskInfo = createTaskInfo(/* hasSizeCompat= */ false, CAMERA_COMPAT_CONTROL_HIDDEN);
+ mTaskInfo = createTaskInfo(/* hasSizeCompat= */ false);
mWindowManager = new UserAspectRatioSettingsWindowManager(mContext, mTaskInfo,
mSyncTransactionQueue, mTaskListener, new DisplayLayout(),
new CompatUIController.CompatUIHintsState(),
@@ -155,13 +152,10 @@
verify(mLayout).setUserAspectRatioSettingsHintVisibility(/* show= */ false);
}
- private static TaskInfo createTaskInfo(boolean hasSizeCompat,
- @CameraCompatControlState int cameraCompatControlState) {
+ private static TaskInfo createTaskInfo(boolean hasSizeCompat) {
ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
taskInfo.taskId = TASK_ID;
taskInfo.appCompatTaskInfo.topActivityInSizeCompat = hasSizeCompat;
- taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState =
- cameraCompatControlState;
taskInfo.realActivity = new ComponentName("com.mypackage.test", "TestActivity");
return taskInfo;
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/CompatUIStateUtil.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/CompatUIStateUtil.kt
new file mode 100644
index 0000000..43bd412
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/CompatUIStateUtil.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.compatui.impl
+
+import com.android.wm.shell.compatui.api.CompatUIComponentState
+import com.android.wm.shell.compatui.api.CompatUISpec
+import com.android.wm.shell.compatui.api.CompatUIState
+import junit.framework.Assert.assertEquals
+import junit.framework.Assert.assertNotNull
+import junit.framework.Assert.assertNull
+
+/**
+ * Asserts no component state exists for the given CompatUISpec
+ */
+internal fun CompatUIState.assertHasNoStateFor(componentId: String) =
+ assertNull(stateForComponent(componentId))
+
+/**
+ * Asserts component state for the given CompatUISpec
+ */
+internal fun CompatUIState.assertHasStateEqualsTo(
+ componentId: String,
+ expected: CompatUIComponentState
+) =
+ assertEquals(stateForComponent(componentId), expected)
+
+/**
+ * Asserts no component exists for the given CompatUISpec
+ */
+internal fun CompatUIState.assertHasNoComponentFor(componentId: String) =
+ assertNull(getUIComponent(componentId))
+
+/**
+ * Asserts component for the given CompatUISpec
+ */
+internal fun CompatUIState.assertHasComponentFor(componentId: String) =
+ assertNotNull(getUIComponent(componentId))
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/DefaultCompatUIHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/DefaultCompatUIHandlerTest.kt
new file mode 100644
index 0000000..8136074
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/DefaultCompatUIHandlerTest.kt
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.compatui.impl
+
+import android.app.ActivityManager
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.wm.shell.compatui.api.CompatUIComponentState
+import com.android.wm.shell.compatui.api.CompatUIInfo
+import com.android.wm.shell.compatui.api.CompatUIState
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Tests for {@link DefaultCompatUIHandler}.
+ *
+ * Build/Install/Run:
+ * atest WMShellUnitTests:DefaultCompatUIHandlerTest
+ */
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class DefaultCompatUIHandlerTest {
+
+ lateinit var compatUIRepository: FakeCompatUIRepository
+ lateinit var compatUIHandler: DefaultCompatUIHandler
+ lateinit var compatUIState: CompatUIState
+ lateinit var fakeIdGenerator: FakeCompatUIComponentIdGenerator
+
+ @Before
+ fun setUp() {
+ compatUIRepository = FakeCompatUIRepository()
+ compatUIState = CompatUIState()
+ fakeIdGenerator = FakeCompatUIComponentIdGenerator("compId")
+ compatUIHandler = DefaultCompatUIHandler(compatUIRepository, compatUIState,
+ fakeIdGenerator)
+ }
+
+ @Test
+ fun `when creationReturn is false no state is stored`() {
+ // We add a spec to the repository
+ val fakeLifecycle = FakeCompatUILifecyclePredicates(
+ creationReturn = false,
+ removalReturn = false
+ )
+ val fakeCompatUISpec = FakeCompatUISpec("one", fakeLifecycle).getSpec()
+ compatUIRepository.addSpec(fakeCompatUISpec)
+
+ val generatedId = fakeIdGenerator.generatedComponentId
+
+ compatUIHandler.onCompatInfoChanged(testCompatUIInfo())
+
+ fakeIdGenerator.assertGenerateInvocations(1)
+ fakeLifecycle.assertCreationInvocation(1)
+ fakeLifecycle.assertRemovalInvocation(0)
+ fakeLifecycle.assertInitialStateInvocation(0)
+ compatUIState.assertHasNoStateFor(generatedId)
+ compatUIState.assertHasNoComponentFor(generatedId)
+
+ compatUIHandler.onCompatInfoChanged(testCompatUIInfo())
+ fakeLifecycle.assertCreationInvocation(2)
+ fakeLifecycle.assertRemovalInvocation(0)
+ fakeLifecycle.assertInitialStateInvocation(0)
+ compatUIState.assertHasNoStateFor(generatedId)
+ compatUIState.assertHasNoComponentFor(generatedId)
+ }
+
+ @Test
+ fun `when creationReturn is true and no state is created no state is stored`() {
+ // We add a spec to the repository
+ val fakeLifecycle = FakeCompatUILifecyclePredicates(
+ creationReturn = true,
+ removalReturn = false
+ )
+ val fakeCompatUISpec = FakeCompatUISpec("one", fakeLifecycle).getSpec()
+ compatUIRepository.addSpec(fakeCompatUISpec)
+
+ val generatedId = fakeIdGenerator.generatedComponentId
+
+ compatUIHandler.onCompatInfoChanged(testCompatUIInfo())
+
+ fakeLifecycle.assertCreationInvocation(1)
+ fakeLifecycle.assertRemovalInvocation(0)
+ fakeLifecycle.assertInitialStateInvocation(1)
+ compatUIState.assertHasNoStateFor(generatedId)
+ compatUIState.assertHasComponentFor(generatedId)
+
+ compatUIHandler.onCompatInfoChanged(testCompatUIInfo())
+
+ fakeLifecycle.assertCreationInvocation(1)
+ fakeLifecycle.assertRemovalInvocation(1)
+ fakeLifecycle.assertInitialStateInvocation(1)
+ compatUIState.assertHasNoStateFor(generatedId)
+ compatUIState.assertHasComponentFor(generatedId)
+ }
+
+ @Test
+ fun `when creationReturn is true and state is created state is stored`() {
+ val fakeComponentState = object : CompatUIComponentState {}
+ // We add a spec to the repository
+ val fakeLifecycle = FakeCompatUILifecyclePredicates(
+ creationReturn = true,
+ removalReturn = false,
+ initialState = { _, _ -> fakeComponentState }
+ )
+ val fakeCompatUISpec = FakeCompatUISpec("one", fakeLifecycle).getSpec()
+ compatUIRepository.addSpec(fakeCompatUISpec)
+
+ val generatedId = fakeIdGenerator.generatedComponentId
+
+ compatUIHandler.onCompatInfoChanged(testCompatUIInfo())
+
+ fakeLifecycle.assertCreationInvocation(1)
+ fakeLifecycle.assertRemovalInvocation(0)
+ fakeLifecycle.assertInitialStateInvocation(1)
+ compatUIState.assertHasStateEqualsTo(generatedId, fakeComponentState)
+ compatUIState.assertHasComponentFor(generatedId)
+
+ compatUIHandler.onCompatInfoChanged(testCompatUIInfo())
+
+ fakeLifecycle.assertCreationInvocation(1)
+ fakeLifecycle.assertRemovalInvocation(1)
+ fakeLifecycle.assertInitialStateInvocation(1)
+ compatUIState.assertHasStateEqualsTo(generatedId, fakeComponentState)
+ compatUIState.assertHasComponentFor(generatedId)
+ }
+
+ @Test
+ fun `when lifecycle is complete and state is created state is stored and removed`() {
+ val fakeComponentState = object : CompatUIComponentState {}
+ // We add a spec to the repository
+ val fakeLifecycle = FakeCompatUILifecyclePredicates(
+ creationReturn = true,
+ removalReturn = true,
+ initialState = { _, _ -> fakeComponentState }
+ )
+ val fakeCompatUISpec = FakeCompatUISpec("one", fakeLifecycle).getSpec()
+ compatUIRepository.addSpec(fakeCompatUISpec)
+
+ val generatedId = fakeIdGenerator.generatedComponentId
+
+ compatUIHandler.onCompatInfoChanged(testCompatUIInfo())
+
+ fakeLifecycle.assertCreationInvocation(1)
+ fakeLifecycle.assertRemovalInvocation(0)
+ fakeLifecycle.assertInitialStateInvocation(1)
+ compatUIState.assertHasStateEqualsTo(generatedId, fakeComponentState)
+ compatUIState.assertHasComponentFor(generatedId)
+
+ compatUIHandler.onCompatInfoChanged(testCompatUIInfo())
+
+ fakeLifecycle.assertCreationInvocation(1)
+ fakeLifecycle.assertRemovalInvocation(1)
+ fakeLifecycle.assertInitialStateInvocation(1)
+ compatUIState.assertHasNoStateFor(generatedId)
+ compatUIState.assertHasNoComponentFor(generatedId)
+ }
+
+ @Test
+ fun `idGenerator is invoked every time a component is created`() {
+ // We add a spec to the repository
+ val fakeLifecycle = FakeCompatUILifecyclePredicates(
+ creationReturn = true,
+ removalReturn = true,
+ )
+ val fakeCompatUISpec = FakeCompatUISpec("one", fakeLifecycle).getSpec()
+ compatUIRepository.addSpec(fakeCompatUISpec)
+ // Component creation
+ fakeIdGenerator.assertGenerateInvocations(0)
+ compatUIHandler.onCompatInfoChanged(testCompatUIInfo())
+ fakeIdGenerator.assertGenerateInvocations(1)
+
+ compatUIHandler.onCompatInfoChanged(testCompatUIInfo())
+ fakeIdGenerator.assertGenerateInvocations(2)
+ }
+
+ private fun testCompatUIInfo(): CompatUIInfo {
+ val taskInfo = ActivityManager.RunningTaskInfo()
+ taskInfo.taskId = 1
+ return CompatUIInfo(taskInfo, null)
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/DefaultCompatUIRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/DefaultCompatUIRepositoryTest.kt
index 1a86cfd..e35acb2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/DefaultCompatUIRepositoryTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/DefaultCompatUIRepositoryTest.kt
@@ -19,6 +19,7 @@
import android.platform.test.flag.junit.DeviceFlagsValueProvider
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
+import com.android.wm.shell.compatui.api.CompatUILifecyclePredicates
import com.android.wm.shell.compatui.api.CompatUIRepository
import com.android.wm.shell.compatui.api.CompatUISpec
import org.junit.Assert.assertEquals
@@ -50,16 +51,16 @@
@Test(expected = IllegalStateException::class)
fun `addSpec throws exception with specs with duplicate id`() {
- repository.addSpec(CompatUISpec("one"))
- repository.addSpec(CompatUISpec("one"))
+ repository.addSpec(specById("one"))
+ repository.addSpec(specById("one"))
}
@Test
fun `iterateOn invokes the consumer`() {
with(repository) {
- addSpec(CompatUISpec("one"))
- addSpec(CompatUISpec("two"))
- addSpec(CompatUISpec("three"))
+ addSpec(specById("one"))
+ addSpec(specById("two"))
+ addSpec(specById("three"))
val consumer = object : (CompatUISpec) -> Unit {
var acc = ""
override fun invoke(spec: CompatUISpec) {
@@ -74,9 +75,9 @@
@Test
fun `findSpec returns existing specs`() {
with(repository) {
- val one = CompatUISpec("one")
- val two = CompatUISpec("two")
- val three = CompatUISpec("three")
+ val one = specById("one")
+ val two = specById("two")
+ val three = specById("three")
addSpec(one)
addSpec(two)
addSpec(three)
@@ -86,4 +87,10 @@
assertNull(findSpec("abc"))
}
}
+
+ private fun specById(name: String): CompatUISpec =
+ CompatUISpec(name = name, lifecycle = CompatUILifecyclePredicates(
+ creationPredicate = { _, _ -> true },
+ removalPredicate = { _, _, _ -> true }
+ ))
}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUIComponentIdGenerator.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUIComponentIdGenerator.kt
new file mode 100644
index 0000000..bc743ed
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUIComponentIdGenerator.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.compatui.impl
+
+import com.android.wm.shell.compatui.api.CompatUIComponentIdGenerator
+import com.android.wm.shell.compatui.api.CompatUIInfo
+import com.android.wm.shell.compatui.api.CompatUISpec
+import junit.framework.Assert.assertEquals
+
+/**
+ * A Fake {@link CompatUIComponentIdGenerator} implementation.
+ */
+class FakeCompatUIComponentIdGenerator(var generatedComponentId: String = "compId") :
+ CompatUIComponentIdGenerator {
+
+ var generateInvocations = 0
+
+ override fun generateId(compatUIInfo: CompatUIInfo, spec: CompatUISpec): String {
+ generateInvocations++
+ return generatedComponentId
+ }
+
+ fun resetInvocations() {
+ generateInvocations = 0
+ }
+
+ fun assertGenerateInvocations(expected: Int) =
+ assertEquals(expected, generateInvocations)
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUILifecyclePredicates.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUILifecyclePredicates.kt
new file mode 100644
index 0000000..bbaa2db
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUILifecyclePredicates.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.compatui.impl
+
+import com.android.wm.shell.compatui.api.CompatUIComponentState
+import com.android.wm.shell.compatui.api.CompatUIInfo
+import com.android.wm.shell.compatui.api.CompatUILifecyclePredicates
+import com.android.wm.shell.compatui.api.CompatUISharedState
+import junit.framework.Assert.assertEquals
+
+/**
+ * Fake class for {@link CompatUILifecycle}
+ */
+class FakeCompatUILifecyclePredicates(
+ private val creationReturn: Boolean,
+ private val removalReturn: Boolean,
+ private val initialState: (
+ CompatUIInfo,
+ CompatUISharedState
+ ) -> CompatUIComponentState? = { _, _ -> null }
+) {
+ var creationInvocation = 0
+ var removalInvocation = 0
+ var initialStateInvocation = 0
+ var lastCreationCompatUIInfo: CompatUIInfo? = null
+ var lastCreationSharedState: CompatUISharedState? = null
+ var lastRemovalCompatUIInfo: CompatUIInfo? = null
+ var lastRemovalSharedState: CompatUISharedState? = null
+ var lastRemovalCompState: CompatUIComponentState? = null
+ fun getLifecycle() = CompatUILifecyclePredicates(
+ creationPredicate = { uiInfo, sharedState ->
+ lastCreationCompatUIInfo = uiInfo
+ lastCreationSharedState = sharedState
+ creationInvocation++
+ creationReturn
+ },
+ removalPredicate = { uiInfo, sharedState, compState ->
+ lastRemovalCompatUIInfo = uiInfo
+ lastRemovalSharedState = sharedState
+ lastRemovalCompState = compState
+ removalInvocation++
+ removalReturn
+ },
+ stateBuilder = { a, b -> initialStateInvocation++; initialState(a, b) }
+ )
+
+ fun assertCreationInvocation(expected: Int) =
+ assertEquals(expected, creationInvocation)
+
+ fun assertRemovalInvocation(expected: Int) =
+ assertEquals(expected, removalInvocation)
+
+ fun assertInitialStateInvocation(expected: Int) =
+ assertEquals(expected, initialStateInvocation)
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUISpec.kt
similarity index 62%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
copy to libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUISpec.kt
index 1f04a44..1ecd52e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUISpec.kt
@@ -14,12 +14,19 @@
* limitations under the License.
*/
-package com.android.systemui.activatable
+package com.android.wm.shell.compatui.impl
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.TestScope
+import com.android.wm.shell.compatui.api.CompatUISpec
-/** Activates [activatable] for the duration of the test. */
-fun Activatable.activateIn(testScope: TestScope) {
- testScope.backgroundScope.launch { activate() }
+/**
+ * Fake implementation for {@link ompatUISpec}
+ */
+class FakeCompatUISpec(
+ val name: String,
+ val lifecycle: FakeCompatUILifecyclePredicates
+) {
+ fun getSpec(): CompatUISpec = CompatUISpec(
+ name = name,
+ lifecycle = lifecycle.getLifecycle()
+ )
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepositoryTest.kt
index 9dc3401..d3404f7 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepositoryTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepositoryTest.kt
@@ -158,8 +158,8 @@
}
@Test
- fun updateVisibleFreeformTasks_singleVisibleNonClosingTask_updatesTasksCorrectly() {
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
+ fun updateTaskVisibility_singleVisibleNonClosingTask_updatesTasksCorrectly() {
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true)
assertThat(repo.isVisibleTask(1)).isTrue()
assertThat(repo.isClosingTask(1)).isFalse()
@@ -172,7 +172,7 @@
@Test
fun isOnlyVisibleNonClosingTask_singleVisibleClosingTask() {
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true)
repo.addClosingTask(DEFAULT_DISPLAY, 1)
// A visible task that's closing
@@ -186,7 +186,7 @@
@Test
fun isOnlyVisibleNonClosingTask_singleVisibleMinimizedTask() {
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true)
repo.minimizeTask(DEFAULT_DISPLAY, 1)
// The visible task that's closing
@@ -200,8 +200,8 @@
@Test
fun isOnlyVisibleNonClosingTask_multipleVisibleNonClosingTasks() {
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = true)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 2, visible = true)
// Not the only task
assertThat(repo.isVisibleTask(1)).isTrue()
@@ -219,9 +219,9 @@
@Test
fun isOnlyVisibleNonClosingTask_multipleDisplays() {
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = true)
- repo.updateVisibleFreeformTasks(SECOND_DISPLAY, taskId = 3, visible = true)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 2, visible = true)
+ repo.updateTaskVisibility(SECOND_DISPLAY, taskId = 3, visible = true)
// Not the only task on DEFAULT_DISPLAY
assertThat(repo.isVisibleTask(1)).isTrue()
@@ -239,7 +239,7 @@
@Test
fun addVisibleTasksListener_notifiesVisibleFreeformTask() {
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true)
val listener = TestVisibilityListener()
val executor = TestShellExecutor()
@@ -252,7 +252,7 @@
@Test
fun addListener_tasksOnDifferentDisplay_doesNotNotify() {
- repo.updateVisibleFreeformTasks(SECOND_DISPLAY, taskId = 1, visible = true)
+ repo.updateTaskVisibility(SECOND_DISPLAY, taskId = 1, visible = true)
val listener = TestVisibilityListener()
val executor = TestShellExecutor()
repo.addVisibleTasksListener(listener, executor)
@@ -264,13 +264,13 @@
}
@Test
- fun updateVisibleFreeformTasks_addVisibleTasksNotifiesListener() {
+ fun updateTaskVisibility_addVisibleTasksNotifiesListener() {
val listener = TestVisibilityListener()
val executor = TestShellExecutor()
repo.addVisibleTasksListener(listener, executor)
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = true)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 2, visible = true)
executor.flushAll()
assertThat(listener.visibleTasksCountOnDefaultDisplay).isEqualTo(2)
@@ -278,12 +278,12 @@
}
@Test
- fun updateVisibleFreeformTasks_addVisibleTaskNotifiesListenerForThatDisplay() {
+ fun updateTaskVisibility_addVisibleTaskNotifiesListenerForThatDisplay() {
val listener = TestVisibilityListener()
val executor = TestShellExecutor()
repo.addVisibleTasksListener(listener, executor)
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true)
executor.flushAll()
assertThat(listener.visibleTasksCountOnDefaultDisplay).isEqualTo(1)
@@ -291,7 +291,7 @@
assertThat(listener.visibleTasksCountOnSecondaryDisplay).isEqualTo(0)
assertThat(listener.visibleChangesOnSecondaryDisplay).isEqualTo(0)
- repo.updateVisibleFreeformTasks(displayId = 1, taskId = 2, visible = true)
+ repo.updateTaskVisibility(displayId = 1, taskId = 2, visible = true)
executor.flushAll()
// Listener for secondary display is notified
@@ -302,17 +302,17 @@
}
@Test
- fun updateVisibleFreeformTasks_taskOnDefaultBecomesVisibleOnSecondDisplay_listenersNotified() {
+ fun updateTaskVisibility_taskOnDefaultBecomesVisibleOnSecondDisplay_listenersNotified() {
val listener = TestVisibilityListener()
val executor = TestShellExecutor()
repo.addVisibleTasksListener(listener, executor)
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true)
executor.flushAll()
assertThat(listener.visibleTasksCountOnDefaultDisplay).isEqualTo(1)
// Mark task 1 visible on secondary display
- repo.updateVisibleFreeformTasks(displayId = 1, taskId = 1, visible = true)
+ repo.updateTaskVisibility(displayId = 1, taskId = 1, visible = true)
executor.flushAll()
// Default display should have 2 calls
@@ -327,22 +327,22 @@
}
@Test
- fun updateVisibleFreeformTasks_removeVisibleTasksNotifiesListener() {
+ fun updateTaskVisibility_removeVisibleTasksNotifiesListener() {
val listener = TestVisibilityListener()
val executor = TestShellExecutor()
repo.addVisibleTasksListener(listener, executor)
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = true)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 2, visible = true)
executor.flushAll()
assertThat(listener.visibleTasksCountOnDefaultDisplay).isEqualTo(2)
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = false)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = false)
executor.flushAll()
assertThat(listener.visibleChangesOnDefaultDisplay).isEqualTo(3)
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = false)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 2, visible = false)
executor.flushAll()
assertThat(listener.visibleTasksCountOnDefaultDisplay).isEqualTo(0)
@@ -354,17 +354,17 @@
* This tests that task is removed from the last parent display when it vanishes.
*/
@Test
- fun updateVisibleFreeformTasks_removeVisibleTasksRemovesTaskWithInvalidDisplay() {
+ fun updateTaskVisibility_removeVisibleTasksRemovesTaskWithInvalidDisplay() {
val listener = TestVisibilityListener()
val executor = TestShellExecutor()
repo.addVisibleTasksListener(listener, executor)
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = true)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 2, visible = true)
executor.flushAll()
assertThat(listener.visibleTasksCountOnDefaultDisplay).isEqualTo(2)
- repo.updateVisibleFreeformTasks(INVALID_DISPLAY, taskId = 1, visible = false)
+ repo.updateTaskVisibility(INVALID_DISPLAY, taskId = 1, visible = false)
executor.flushAll()
assertThat(listener.visibleChangesOnDefaultDisplay).isEqualTo(3)
@@ -377,30 +377,30 @@
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0)
// New task increments count to 1
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true)
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(1)
// Visibility update to same task does not increase count
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true)
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(1)
// Second task visible increments count
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = true)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 2, visible = true)
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(2)
// Hiding a task decrements count
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = false)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = false)
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(1)
// Hiding all tasks leaves count at 0
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = false)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 2, visible = false)
assertThat(repo.getVisibleTaskCount(displayId = 9)).isEqualTo(0)
// Hiding a not existing task, count remains at 0
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 999, visible = false)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 999, visible = false)
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0)
}
@@ -410,32 +410,32 @@
assertThat(repo.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(0)
// New task on default display increments count for that display only
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true)
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(1)
assertThat(repo.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(0)
// New task on secondary display, increments count for that display only
- repo.updateVisibleFreeformTasks(SECOND_DISPLAY, taskId = 2, visible = true)
+ repo.updateTaskVisibility(SECOND_DISPLAY, taskId = 2, visible = true)
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(1)
assertThat(repo.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(1)
// Marking task visible on another display, updates counts for both displays
- repo.updateVisibleFreeformTasks(SECOND_DISPLAY, taskId = 1, visible = true)
+ repo.updateTaskVisibility(SECOND_DISPLAY, taskId = 1, visible = true)
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0)
assertThat(repo.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(2)
// Marking task that is on secondary display, hidden on default display, does not affect
// secondary display
- repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = false)
+ repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = false)
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0)
assertThat(repo.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(2)
// Hiding a task on that display, decrements count
- repo.updateVisibleFreeformTasks(SECOND_DISPLAY, taskId = 1, visible = false)
+ repo.updateTaskVisibility(SECOND_DISPLAY, taskId = 1, visible = false)
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0)
assertThat(repo.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(1)
@@ -468,6 +468,29 @@
}
@Test
+ fun addOrMoveFreeformTaskToTop_taskIsMinimized_unminimizesTask() {
+ repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, 5)
+ repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, 6)
+ repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, 7)
+ repo.minimizeTask(displayId = 0, taskId = 6)
+
+ val tasks = repo.getFreeformTasksInZOrder(DEFAULT_DISPLAY)
+ assertThat(tasks).containsExactly(7, 6, 5).inOrder()
+ assertThat(repo.isMinimizedTask(taskId = 6)).isTrue()
+ }
+
+ @Test
+ fun addOrMoveFreeformTaskToTop_taskIsUnminimized_noop() {
+ repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, 5)
+ repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, 6)
+ repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, 7)
+
+ val tasks = repo.getFreeformTasksInZOrder(DEFAULT_DISPLAY)
+ assertThat(tasks).containsExactly(7, 6, 5).inOrder()
+ assertThat(repo.isMinimizedTask(taskId = 6)).isFalse()
+ }
+
+ @Test
fun removeFreeformTask_invalidDisplay_removesTaskFromFreeformTasks() {
repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, taskId = 1)
@@ -512,6 +535,43 @@
}
@Test
+ fun removeFreeformTask_removesActiveTask() {
+ val taskId = 1
+ val listener = TestListener()
+ repo.addActiveTaskListener(listener)
+ repo.addActiveTask(DEFAULT_DISPLAY, taskId)
+ repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, taskId)
+
+ repo.removeFreeformTask(THIRD_DISPLAY, taskId)
+
+ assertThat(repo.isActiveTask(taskId)).isFalse()
+ assertThat(listener.activeChangesOnDefaultDisplay).isEqualTo(2)
+ }
+
+ @Test
+ fun removeFreeformTask_unminimizesTask() {
+ val taskId = 1
+ repo.addActiveTask(DEFAULT_DISPLAY, taskId)
+ repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, taskId)
+ repo.minimizeTask(DEFAULT_DISPLAY, taskId)
+
+ repo.removeFreeformTask(DEFAULT_DISPLAY, taskId)
+
+ assertThat(repo.isMinimizedTask(taskId)).isFalse()
+ }
+
+ @Test
+ fun removeFreeformTask_updatesTaskVisibility() {
+ val taskId = 1
+ repo.addActiveTask(DEFAULT_DISPLAY, taskId)
+ repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, taskId)
+
+ repo.removeFreeformTask(THIRD_DISPLAY, taskId)
+
+ assertThat(repo.isVisibleTask(taskId)).isFalse()
+ }
+
+ @Test
fun saveBoundsBeforeMaximize_boundsSavedByTaskId() {
val taskId = 1
val bounds = Rect(0, 0, 200, 200)
@@ -571,9 +631,9 @@
@Test
- fun updateVisibleFreeformTasks_minimizedTaskBecomesVisible_unminimizesTask() {
+ fun updateTaskVisibility_minimizedTaskBecomesVisible_unminimizesTask() {
repo.minimizeTask(displayId = 10, taskId = 2)
- repo.updateVisibleFreeformTasks(displayId = 10, taskId = 2, visible = true)
+ repo.updateTaskVisibility(displayId = 10, taskId = 2, visible = true)
val isMinimizedTask = repo.isMinimizedTask(taskId = 2)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index 2368cef..76939f6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -85,6 +85,7 @@
import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource.UNKNOWN
import com.android.wm.shell.common.split.SplitScreenConstants
+import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFullscreenTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createHomeTask
@@ -117,7 +118,6 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
-import org.mockito.ArgumentMatchers.eq
import org.mockito.ArgumentMatchers.isA
import org.mockito.ArgumentMatchers.isNull
import org.mockito.Mock
@@ -128,10 +128,11 @@
import org.mockito.Mockito.mock
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
import org.mockito.kotlin.anyOrNull
import org.mockito.kotlin.atLeastOnce
+import org.mockito.kotlin.eq
import org.mockito.kotlin.capture
+import org.mockito.kotlin.whenever
import org.mockito.quality.Strictness
/**
@@ -156,6 +157,7 @@
@Mock lateinit var rootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer
@Mock lateinit var transitions: Transitions
@Mock lateinit var keyguardManager: KeyguardManager
+ @Mock lateinit var mReturnToDragStartAnimator: ReturnToDragStartAnimator
@Mock lateinit var exitDesktopTransitionHandler: ExitDesktopTaskTransitionHandler
@Mock lateinit var enterDesktopTransitionHandler: EnterDesktopTaskTransitionHandler
@Mock
@@ -176,7 +178,7 @@
private lateinit var mockitoSession: StaticMockitoSession
private lateinit var controller: DesktopTasksController
private lateinit var shellInit: ShellInit
- private lateinit var desktopModeTaskRepository: DesktopModeTaskRepository
+ private lateinit var taskRepository: DesktopModeTaskRepository
private lateinit var desktopTasksLimiter: DesktopTasksLimiter
private lateinit var recentsTransitionStateListener: RecentsTransitionStateListener
@@ -204,14 +206,15 @@
doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
shellInit = spy(ShellInit(testExecutor))
- desktopModeTaskRepository = DesktopModeTaskRepository()
+ taskRepository = DesktopModeTaskRepository()
desktopTasksLimiter =
DesktopTasksLimiter(
transitions,
- desktopModeTaskRepository,
+ taskRepository,
shellTaskOrganizer,
MAX_TASK_LIMIT,
- )
+ mockInteractionJankMonitor,
+ mContext)
whenever(shellTaskOrganizer.getRunningTasks(anyInt())).thenAnswer { runningTasks }
whenever(transitions.startTransition(anyInt(), any(), isNull())).thenAnswer { Binder() }
@@ -248,11 +251,12 @@
dragAndDropController,
transitions,
keyguardManager,
+ mReturnToDragStartAnimator,
enterDesktopTransitionHandler,
exitDesktopTransitionHandler,
toggleResizeDesktopTaskTransitionHandler,
dragToDesktopTransitionHandler,
- desktopModeTaskRepository,
+ taskRepository,
desktopModeLoggerTransitionObserver,
launchAdjacentController,
recentsTransitionHandler,
@@ -276,7 +280,7 @@
}
@Test
- fun instantiate_canNotEnterDesktopMode_doNotAddInitCallback() {
+ fun instantiate_cannotEnterDesktopMode_doNotAddInitCallback() {
whenever(DesktopModeStatus.canEnterDesktopMode(context)).thenReturn(false)
clearInvocations(shellInit)
@@ -530,7 +534,7 @@
markTaskHidden(freeformTask)
markTaskHidden(minimizedTask)
- desktopModeTaskRepository.minimizeTask(DEFAULT_DISPLAY, minimizedTask.taskId)
+ taskRepository.minimizeTask(DEFAULT_DISPLAY, minimizedTask.taskId)
controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition()))
val wct = getLatestWct(type = TRANSIT_TO_FRONT, handlerClass = OneShotRemoteHandler::class.java)
@@ -549,7 +553,7 @@
markTaskHidden(freeformTask)
markTaskHidden(minimizedTask)
- desktopModeTaskRepository.minimizeTask(DEFAULT_DISPLAY, minimizedTask.taskId)
+ taskRepository.minimizeTask(DEFAULT_DISPLAY, minimizedTask.taskId)
controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition()))
val wct = getLatestWct(type = TRANSIT_TO_FRONT, handlerClass = OneShotRemoteHandler::class.java)
@@ -751,36 +755,36 @@
val task = setUpFullscreenTask()
val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!!
tda.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN
- controller.moveToDesktop(task, transitionSource = UNKNOWN)
+ controller.moveRunningTaskToDesktop(task, transitionSource = UNKNOWN)
val wct = getLatestEnterDesktopWct()
assertThat(wct.changes[task.token.asBinder()]?.windowingMode).isEqualTo(WINDOWING_MODE_FREEFORM)
}
@Test
- fun moveToDesktop_tdaFreeform_windowingModeSetToUndefined() {
+ fun moveRunningTaskToDesktop_tdaFreeform_windowingModeSetToUndefined() {
val task = setUpFullscreenTask()
val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!!
tda.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FREEFORM
- controller.moveToDesktop(task, transitionSource = UNKNOWN)
+ controller.moveRunningTaskToDesktop(task, transitionSource = UNKNOWN)
val wct = getLatestEnterDesktopWct()
assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
.isEqualTo(WINDOWING_MODE_UNDEFINED)
}
@Test
- fun moveToDesktop_nonExistentTask_doesNothing() {
- controller.moveToDesktop(999, transitionSource = UNKNOWN)
+ fun moveTaskToDesktop_nonExistentTask_doesNothing() {
+ controller.moveTaskToDesktop(999, transitionSource = UNKNOWN)
verifyEnterDesktopWCTNotExecuted()
}
@Test
@DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
- fun moveToDesktop_desktopWallpaperDisabled_nonRunningTask_launchesInFreeform() {
+ fun moveTaskToDesktop_desktopWallpaperDisabled_nonRunningTask_launchesInFreeform() {
val task = createTaskInfo(1)
whenever(shellTaskOrganizer.getRunningTaskInfo(anyInt())).thenReturn(null)
whenever(recentTasksController.findTaskInBackground(anyInt())).thenReturn(task)
- controller.moveToDesktop(task.taskId, transitionSource = UNKNOWN)
+ controller.moveTaskToDesktop(task.taskId, transitionSource = UNKNOWN)
with(getLatestEnterDesktopWct()) {
assertLaunchTaskAt(0, task.taskId, WINDOWING_MODE_FREEFORM)
@@ -789,12 +793,12 @@
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
- fun moveToDesktop_desktopWallpaperEnabled_nonRunningTask_launchesInFreeform() {
+ fun moveTaskToDesktop_desktopWallpaperEnabled_nonRunningTask_launchesInFreeform() {
val task = createTaskInfo(1)
whenever(shellTaskOrganizer.getRunningTaskInfo(anyInt())).thenReturn(null)
whenever(recentTasksController.findTaskInBackground(anyInt())).thenReturn(task)
- controller.moveToDesktop(task.taskId, transitionSource = UNKNOWN)
+ controller.moveTaskToDesktop(task.taskId, transitionSource = UNKNOWN)
with(getLatestEnterDesktopWct()) {
// Add desktop wallpaper activity
@@ -806,7 +810,7 @@
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
- fun moveToDesktop_topActivityTranslucentWithStyleFloating_taskIsMovedToDesktop() {
+ fun moveRunningTaskToDesktop_topActivityTranslucentWithStyleFloating_taskIsMovedToDesktop() {
val task =
setUpFullscreenTask().apply {
isTopActivityTransparent = true
@@ -814,7 +818,7 @@
numActivities = 1
}
- controller.moveToDesktop(task, transitionSource = UNKNOWN)
+ controller.moveRunningTaskToDesktop(task, transitionSource = UNKNOWN)
val wct = getLatestEnterDesktopWct()
assertThat(wct.changes[task.token.asBinder()]?.windowingMode).isEqualTo(WINDOWING_MODE_FREEFORM)
@@ -822,7 +826,7 @@
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
- fun moveToDesktop_topActivityTranslucentWithoutStyleFloating_doesNothing() {
+ fun moveRunningTaskToDesktop_topActivityTranslucentWithoutStyleFloating_doesNothing() {
val task =
setUpFullscreenTask().apply {
isTopActivityTransparent = true
@@ -830,13 +834,13 @@
numActivities = 1
}
- controller.moveToDesktop(task, transitionSource = UNKNOWN)
+ controller.moveRunningTaskToDesktop(task, transitionSource = UNKNOWN)
verifyEnterDesktopWCTNotExecuted()
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
- fun moveToDesktop_systemUIActivity_doesNothing() {
+ fun moveRunningTaskToDesktop_systemUIActivity_doesNothing() {
val task = setUpFullscreenTask()
// Set task as systemUI package
@@ -845,15 +849,15 @@
val baseComponent = ComponentName(systemUIPackageName, /* class */ "")
task.baseActivity = baseComponent
- controller.moveToDesktop(task, transitionSource = UNKNOWN)
+ controller.moveRunningTaskToDesktop(task, transitionSource = UNKNOWN)
verifyEnterDesktopWCTNotExecuted()
}
@Test
- fun moveToDesktop_deviceSupported_taskIsMovedToDesktop() {
+ fun moveRunningTaskToDesktop_deviceSupported_taskIsMovedToDesktop() {
val task = setUpFullscreenTask()
- controller.moveToDesktop(task, transitionSource = UNKNOWN)
+ controller.moveRunningTaskToDesktop(task, transitionSource = UNKNOWN)
val wct = getLatestEnterDesktopWct()
assertThat(wct.changes[task.token.asBinder()]?.windowingMode).isEqualTo(WINDOWING_MODE_FREEFORM)
@@ -861,13 +865,13 @@
@Test
@DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
- fun moveToDesktop_otherFreeformTasksBroughtToFront_desktopWallpaperDisabled() {
+ fun moveRunningTaskToDesktop_otherFreeformTasksBroughtToFront_desktopWallpaperDisabled() {
val homeTask = setUpHomeTask()
val freeformTask = setUpFreeformTask()
val fullscreenTask = setUpFullscreenTask()
markTaskHidden(freeformTask)
- controller.moveToDesktop(fullscreenTask, transitionSource = UNKNOWN)
+ controller.moveRunningTaskToDesktop(fullscreenTask, transitionSource = UNKNOWN)
with(getLatestEnterDesktopWct()) {
// Operations should include home task, freeform task
@@ -880,12 +884,12 @@
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
- fun moveToDesktop_otherFreeformTasksBroughtToFront_desktopWallpaperEnabled() {
+ fun moveRunningTaskToDesktop_otherFreeformTasksBroughtToFront_desktopWallpaperEnabled() {
val freeformTask = setUpFreeformTask()
val fullscreenTask = setUpFullscreenTask()
markTaskHidden(freeformTask)
- controller.moveToDesktop(fullscreenTask, transitionSource = UNKNOWN)
+ controller.moveRunningTaskToDesktop(fullscreenTask, transitionSource = UNKNOWN)
with(getLatestEnterDesktopWct()) {
// Operations should include wallpaper intent, freeform task, fullscreen task
@@ -899,7 +903,7 @@
}
@Test
- fun moveToDesktop_onlyFreeformTasksFromCurrentDisplayBroughtToFront() {
+ fun moveRunningTaskToDesktop_onlyFreeformTasksFromCurrentDisplayBroughtToFront() {
setUpHomeTask(displayId = DEFAULT_DISPLAY)
val freeformTaskDefault = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
val fullscreenTaskDefault = setUpFullscreenTask(displayId = DEFAULT_DISPLAY)
@@ -909,7 +913,7 @@
val freeformTaskSecond = setUpFreeformTask(displayId = SECOND_DISPLAY)
markTaskHidden(freeformTaskSecond)
- controller.moveToDesktop(fullscreenTaskDefault, transitionSource = UNKNOWN)
+ controller.moveRunningTaskToDesktop(fullscreenTaskDefault, transitionSource = UNKNOWN)
with(getLatestEnterDesktopWct()) {
// Check that hierarchy operations do not include tasks from second display
@@ -920,9 +924,9 @@
}
@Test
- fun moveToDesktop_splitTaskExitsSplit() {
+ fun moveRunningTaskToDesktop_splitTaskExitsSplit() {
val task = setUpSplitScreenTask()
- controller.moveToDesktop(task, transitionSource = UNKNOWN)
+ controller.moveRunningTaskToDesktop(task, transitionSource = UNKNOWN)
val wct = getLatestEnterDesktopWct()
assertThat(wct.changes[task.token.asBinder()]?.windowingMode).isEqualTo(WINDOWING_MODE_FREEFORM)
verify(splitScreenController)
@@ -930,9 +934,9 @@
}
@Test
- fun moveToDesktop_fullscreenTaskDoesNotExitSplit() {
+ fun moveRunningTaskToDesktop_fullscreenTaskDoesNotExitSplit() {
val task = setUpFullscreenTask()
- controller.moveToDesktop(task, transitionSource = UNKNOWN)
+ controller.moveRunningTaskToDesktop(task, transitionSource = UNKNOWN)
val wct = getLatestEnterDesktopWct()
assertThat(wct.changes[task.token.asBinder()]?.windowingMode).isEqualTo(WINDOWING_MODE_FREEFORM)
verify(splitScreenController, never())
@@ -941,12 +945,12 @@
@Test
@DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
- fun moveToDesktop_desktopWallpaperDisabled_bringsTasksOver_dontShowBackTask() {
+ fun moveRunningTaskToDesktop_desktopWallpaperDisabled_bringsTasksOver_dontShowBackTask() {
val freeformTasks = (1..MAX_TASK_LIMIT).map { _ -> setUpFreeformTask() }
val newTask = setUpFullscreenTask()
val homeTask = setUpHomeTask()
- controller.moveToDesktop(newTask, transitionSource = UNKNOWN)
+ controller.moveRunningTaskToDesktop(newTask, transitionSource = UNKNOWN)
val wct = getLatestEnterDesktopWct()
assertThat(wct.hierarchyOps.size).isEqualTo(MAX_TASK_LIMIT + 1) // visible tasks + home
@@ -959,12 +963,12 @@
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
- fun moveToDesktop_desktopWallpaperEnabled_bringsTasksOverLimit_dontShowBackTask() {
+ fun moveRunningTaskToDesktop_desktopWallpaperEnabled_bringsTasksOverLimit_dontShowBackTask() {
val freeformTasks = (1..MAX_TASK_LIMIT).map { _ -> setUpFreeformTask() }
val newTask = setUpFullscreenTask()
val homeTask = setUpHomeTask()
- controller.moveToDesktop(newTask, transitionSource = UNKNOWN)
+ controller.moveRunningTaskToDesktop(newTask, transitionSource = UNKNOWN)
val wct = getLatestEnterDesktopWct()
assertThat(wct.hierarchyOps.size).isEqualTo(MAX_TASK_LIMIT + 2) // tasks + home + wallpaper
@@ -995,7 +999,7 @@
val task = setUpFreeformTask()
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.wallpaperActivityToken = wallpaperToken
assertNotNull(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY))
.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN
@@ -1024,7 +1028,7 @@
val task = setUpFreeformTask()
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.wallpaperActivityToken = wallpaperToken
assertNotNull(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY))
.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FREEFORM
@@ -1044,7 +1048,7 @@
setUpFreeformTask()
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.wallpaperActivityToken = wallpaperToken
assertNotNull(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY))
.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN
@@ -1185,7 +1189,7 @@
fun onDesktopWindowClose_singleActiveTask_hasWallpaperActivityToken() {
val task = setUpFreeformTask()
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.wallpaperActivityToken = wallpaperToken
val wct = WindowContainerTransaction()
controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task.taskId)
@@ -1197,8 +1201,8 @@
fun onDesktopWindowClose_singleActiveTask_isClosing() {
val task = setUpFreeformTask()
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
- desktopModeTaskRepository.addClosingTask(DEFAULT_DISPLAY, task.taskId)
+ taskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.addClosingTask(DEFAULT_DISPLAY, task.taskId)
val wct = WindowContainerTransaction()
controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task.taskId)
@@ -1210,8 +1214,8 @@
fun onDesktopWindowClose_singleActiveTask_isMinimized() {
val task = setUpFreeformTask()
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
- desktopModeTaskRepository.minimizeTask(DEFAULT_DISPLAY, task.taskId)
+ taskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.minimizeTask(DEFAULT_DISPLAY, task.taskId)
val wct = WindowContainerTransaction()
controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task.taskId)
@@ -1224,7 +1228,7 @@
val task1 = setUpFreeformTask()
setUpFreeformTask()
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.wallpaperActivityToken = wallpaperToken
val wct = WindowContainerTransaction()
controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task1.taskId)
@@ -1237,8 +1241,8 @@
val task1 = setUpFreeformTask()
val task2 = setUpFreeformTask()
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
- desktopModeTaskRepository.addClosingTask(DEFAULT_DISPLAY, task2.taskId)
+ taskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.addClosingTask(DEFAULT_DISPLAY, task2.taskId)
val wct = WindowContainerTransaction()
controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task1.taskId)
@@ -1251,8 +1255,8 @@
val task1 = setUpFreeformTask()
val task2 = setUpFreeformTask()
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
- desktopModeTaskRepository.minimizeTask(DEFAULT_DISPLAY, task2.taskId)
+ taskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.minimizeTask(DEFAULT_DISPLAY, task2.taskId)
val wct = WindowContainerTransaction()
controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task1.taskId)
@@ -1565,6 +1569,21 @@
}
@Test
+ fun handleRequest_recentsAnimationRunning_relaunchActiveTask_taskBecomesUndefined() {
+ // Set up a visible freeform task
+ val freeformTask = setUpFreeformTask()
+ markTaskVisible(freeformTask)
+
+ // Mark recents animation running
+ recentsTransitionStateListener.onAnimationStateChanged(true)
+
+ // Should become undefined as the TDA is set to fullscreen. It will inherit from the TDA.
+ val result = controller.handleRequest(Binder(), createTransition(freeformTask))
+ assertThat(result?.changes?.get(freeformTask.token.asBinder())?.windowingMode)
+ .isEqualTo(WINDOWING_MODE_UNDEFINED)
+ }
+
+ @Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
fun handleRequest_topActivityTransparentWithStyleFloating_returnSwitchToFreeformWCT() {
val freeformTask = setUpFreeformTask()
@@ -1658,7 +1677,7 @@
fun handleRequest_backTransition_singleTaskWithToken_noWallpaper_noBackNav_doesNotHandle() {
val task = setUpFreeformTask()
- desktopModeTaskRepository.wallpaperActivityToken = MockToken().token()
+ taskRepository.wallpaperActivityToken = MockToken().token()
val result = controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_TO_BACK))
assertNull(result, "Should not handle request")
@@ -1673,7 +1692,7 @@
val task = setUpFreeformTask()
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.wallpaperActivityToken = wallpaperToken
val result = controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_TO_BACK))
// Should create remove wallpaper transaction
@@ -1688,7 +1707,7 @@
val task = setUpFreeformTask()
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.wallpaperActivityToken = wallpaperToken
val result = controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_TO_BACK))
// Should create remove wallpaper transaction
@@ -1704,7 +1723,7 @@
val task1 = setUpFreeformTask()
setUpFreeformTask()
- desktopModeTaskRepository.wallpaperActivityToken = MockToken().token()
+ taskRepository.wallpaperActivityToken = MockToken().token()
val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK))
assertNull(result, "Should not handle request")
@@ -1719,7 +1738,7 @@
val task1 = setUpFreeformTask()
setUpFreeformTask()
- desktopModeTaskRepository.wallpaperActivityToken = MockToken().token()
+ taskRepository.wallpaperActivityToken = MockToken().token()
val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK))
assertNotNull(result, "Should handle request").assertRemoveAt(index = 0, task1.token)
@@ -1732,7 +1751,7 @@
val task1 = setUpFreeformTask()
setUpFreeformTask()
- desktopModeTaskRepository.wallpaperActivityToken = MockToken().token()
+ taskRepository.wallpaperActivityToken = MockToken().token()
val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK))
assertNull(result, "Should not handle request")
@@ -1748,8 +1767,8 @@
val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
- desktopModeTaskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
+ taskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK))
// Should create remove wallpaper transaction
@@ -1765,8 +1784,8 @@
val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
- desktopModeTaskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
+ taskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK))
// Should create remove wallpaper transaction
@@ -1783,8 +1802,8 @@
val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
- desktopModeTaskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
+ taskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK))
// Should create remove wallpaper transaction
@@ -1800,8 +1819,8 @@
val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
- desktopModeTaskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
+ taskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK))
// Should create remove wallpaper transaction
@@ -1818,11 +1837,11 @@
val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
- desktopModeTaskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
+ taskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
// Task is being minimized so mark it as not visible.
- desktopModeTaskRepository
- .updateVisibleFreeformTasks(displayId = DEFAULT_DISPLAY, task2.taskId, false)
+ taskRepository
+ .updateTaskVisibility(displayId = DEFAULT_DISPLAY, task2.taskId, false)
val result = controller.handleRequest(Binder(), createTransition(task2, type = TRANSIT_TO_BACK))
assertNull(result, "Should not handle request")
@@ -1873,7 +1892,7 @@
fun handleRequest_closeTransition_singleTaskWithToken_noWallpaper_noBackNav_doesNotHandle() {
val task = setUpFreeformTask()
- desktopModeTaskRepository.wallpaperActivityToken = MockToken().token()
+ taskRepository.wallpaperActivityToken = MockToken().token()
val result = controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_CLOSE))
assertNull(result, "Should not handle request")
@@ -1888,7 +1907,7 @@
val task = setUpFreeformTask()
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.wallpaperActivityToken = wallpaperToken
val result = controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_CLOSE))
// Should create remove wallpaper transaction
@@ -1903,7 +1922,7 @@
val task = setUpFreeformTask()
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.wallpaperActivityToken = wallpaperToken
val result = controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_CLOSE))
// Should create remove wallpaper transaction
@@ -1919,7 +1938,7 @@
val task1 = setUpFreeformTask()
setUpFreeformTask()
- desktopModeTaskRepository.wallpaperActivityToken = MockToken().token()
+ taskRepository.wallpaperActivityToken = MockToken().token()
val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_CLOSE))
assertNull(result, "Should not handle request")
@@ -1934,7 +1953,7 @@
val task1 = setUpFreeformTask()
setUpFreeformTask()
- desktopModeTaskRepository.wallpaperActivityToken = MockToken().token()
+ taskRepository.wallpaperActivityToken = MockToken().token()
val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_CLOSE))
assertNotNull(result, "Should handle request")
@@ -1948,7 +1967,7 @@
val task1 = setUpFreeformTask()
setUpFreeformTask()
- desktopModeTaskRepository.wallpaperActivityToken = MockToken().token()
+ taskRepository.wallpaperActivityToken = MockToken().token()
val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_CLOSE))
assertNull(result, "Should not handle request")
@@ -1964,8 +1983,8 @@
val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
- desktopModeTaskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
+ taskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_CLOSE))
// Should create remove wallpaper transaction
@@ -1981,8 +2000,8 @@
val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
- desktopModeTaskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
+ taskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_CLOSE))
// Should create remove wallpaper transaction
@@ -1999,8 +2018,8 @@
val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
- desktopModeTaskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
+ taskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_CLOSE))
// Should create remove wallpaper transaction
@@ -2016,8 +2035,8 @@
val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
- desktopModeTaskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
+ taskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_CLOSE))
// Should create remove wallpaper transaction
@@ -2034,11 +2053,11 @@
val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
val wallpaperToken = MockToken().token()
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
- desktopModeTaskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
+ taskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
// Task is being minimized so mark it as not visible.
- desktopModeTaskRepository
- .updateVisibleFreeformTasks(displayId = DEFAULT_DISPLAY, task2.taskId, false)
+ taskRepository
+ .updateTaskVisibility(displayId = DEFAULT_DISPLAY, task2.taskId, false)
val result = controller.handleRequest(Binder(), createTransition(task2, type = TRANSIT_TO_BACK))
assertNull(result, "Should not handle request")
@@ -2132,9 +2151,9 @@
task1.isFocused = false
task2.isFocused = true
task3.isFocused = false
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
- desktopModeTaskRepository.minimizeTask(DEFAULT_DISPLAY, task1.taskId)
- desktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task3.taskId,
+ taskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.minimizeTask(DEFAULT_DISPLAY, task1.taskId)
+ taskRepository.updateTaskVisibility(DEFAULT_DISPLAY, task3.taskId,
visible = false)
controller.enterFullscreen(DEFAULT_DISPLAY, transitionSource = UNKNOWN)
@@ -2155,7 +2174,7 @@
task1.isFocused = false
task2.isFocused = true
task3.isFocused = false
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.wallpaperActivityToken = wallpaperToken
controller.enterFullscreen(DEFAULT_DISPLAY, transitionSource = UNKNOWN)
val wct = getLatestExitDesktopWct()
@@ -2358,10 +2377,12 @@
controller.onDragPositioningEnd(
task,
+ mockSurface,
Point(100, -100), /* position */
PointF(200f, -200f), /* inputCoordinate */
- Rect(100, -100, 500, 1000), /* taskBounds */
- Rect(0, 50, 2000, 2000) /* validDragArea */)
+ Rect(100, -100, 500, 1000), /* currentDragBounds */
+ Rect(0, 50, 2000, 2000), /* validDragArea */
+ Rect() /* dragStartBounds */ )
val rectAfterEnd = Rect(100, 50, 500, 1150)
verify(transitions)
.startTransition(
@@ -2375,6 +2396,42 @@
}
@Test
+ fun onDesktopDragEnd_noIndicator_updatesTaskBounds() {
+ val task = setUpFreeformTask()
+ val spyController = spy(controller)
+ val mockSurface = mock(SurfaceControl::class.java)
+ val mockDisplayLayout = mock(DisplayLayout::class.java)
+ whenever(displayController.getDisplayLayout(task.displayId)).thenReturn(mockDisplayLayout)
+ whenever(mockDisplayLayout.stableInsets()).thenReturn(Rect(0, 100, 2000, 2000))
+ spyController.onDragPositioningMove(task, mockSurface, 200f, Rect(100, 200, 500, 1000))
+
+ val currentDragBounds = Rect(100, 200, 500, 1000)
+ whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator)
+ whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull()))
+ .thenReturn(DesktopModeVisualIndicator.IndicatorType.NO_INDICATOR)
+
+ spyController.onDragPositioningEnd(
+ task,
+ mockSurface,
+ Point(100, 200), /* position */
+ PointF(200f, 300f), /* inputCoordinate */
+ currentDragBounds, /* currentDragBounds */
+ Rect(0, 50, 2000, 2000) /* validDragArea */,
+ Rect() /* dragStartBounds */)
+
+
+ verify(transitions)
+ .startTransition(
+ eq(TRANSIT_CHANGE),
+ Mockito.argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ change.configuration.windowConfiguration.bounds == currentDragBounds
+ }
+ },
+ eq(null))
+ }
+
+ @Test
fun enterSplit_freeformTaskIsMovedToSplit() {
val task1 = setUpFreeformTask()
val task2 = setUpFreeformTask()
@@ -2404,9 +2461,9 @@
task1.isFocused = false
task2.isFocused = true
task3.isFocused = false
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
- desktopModeTaskRepository.minimizeTask(DEFAULT_DISPLAY, task1.taskId)
- desktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task3.taskId,
+ taskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.minimizeTask(DEFAULT_DISPLAY, task1.taskId)
+ taskRepository.updateTaskVisibility(DEFAULT_DISPLAY, task3.taskId,
visible = false)
controller.enterSplit(DEFAULT_DISPLAY, leftOrTop = false)
@@ -2432,7 +2489,7 @@
task1.isFocused = false
task2.isFocused = true
task3.isFocused = false
- desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
+ taskRepository.wallpaperActivityToken = wallpaperToken
controller.enterSplit(DEFAULT_DISPLAY, leftOrTop = false)
@@ -2459,6 +2516,63 @@
}
@Test
+ fun getSnapBounds_calculatesBoundsForResizable() {
+ val bounds = Rect(100, 100, 300, 300)
+ val task = setUpFreeformTask(DEFAULT_DISPLAY, bounds).apply {
+ topActivityInfo = ActivityInfo().apply {
+ screenOrientation = SCREEN_ORIENTATION_LANDSCAPE
+ configuration.windowConfiguration.appBounds = bounds
+ }
+ isResizeable = true
+ }
+
+ val currentDragBounds = Rect(0, 100, 200, 300)
+ val expectedBounds = Rect(
+ STABLE_BOUNDS.left, STABLE_BOUNDS.top, STABLE_BOUNDS.right / 2, STABLE_BOUNDS.bottom
+ )
+
+ controller.snapToHalfScreen(task, currentDragBounds, SnapPosition.LEFT)
+ // Assert bounds set to stable bounds
+ val wct = getLatestToggleResizeDesktopTaskWct(currentDragBounds)
+ assertThat(findBoundsChange(wct, task)).isEqualTo(expectedBounds)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_DISABLE_NON_RESIZABLE_APP_SNAP_RESIZING)
+ fun handleSnapResizingTask_nonResizable_snapsToHalfScreen() {
+ val task = setUpFreeformTask(DEFAULT_DISPLAY, Rect(0, 0, 200, 100)).apply {
+ isResizeable = false
+ }
+ val preDragBounds = Rect(100, 100, 400, 500)
+ val currentDragBounds = Rect(0, 100, 300, 500)
+
+ controller.handleSnapResizingTask(
+ task, SnapPosition.LEFT, mockSurface, currentDragBounds, preDragBounds)
+ val wct = getLatestToggleResizeDesktopTaskWct(currentDragBounds)
+ assertThat(findBoundsChange(wct, task)).isEqualTo(
+ Rect(STABLE_BOUNDS.left, STABLE_BOUNDS.top, STABLE_BOUNDS.right / 2, STABLE_BOUNDS.bottom))
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_DISABLE_NON_RESIZABLE_APP_SNAP_RESIZING)
+ fun handleSnapResizingTask_nonResizable_startsRepositionAnimation() {
+ val task = setUpFreeformTask(DEFAULT_DISPLAY, Rect(0, 0, 200, 100)).apply {
+ isResizeable = false
+ }
+ val preDragBounds = Rect(100, 100, 400, 500)
+ val currentDragBounds = Rect(0, 100, 300, 500)
+
+ controller.handleSnapResizingTask(
+ task, SnapPosition.LEFT, mockSurface, currentDragBounds, preDragBounds)
+ verify(mReturnToDragStartAnimator).start(
+ eq(task.taskId),
+ eq(mockSurface),
+ eq(currentDragBounds),
+ eq(preDragBounds)
+ )
+ }
+
+ @Test
fun toggleBounds_togglesToCalculatedBoundsForNonResizable() {
val bounds = Rect(0, 0, 200, 100)
val task = setUpFreeformTask(DEFAULT_DISPLAY, bounds).apply {
@@ -2484,7 +2598,7 @@
val task = setUpFreeformTask(DEFAULT_DISPLAY, bounds)
controller.toggleDesktopTaskSize(task)
- assertThat(desktopModeTaskRepository.removeBoundsBeforeMaximize(task.taskId)).isEqualTo(bounds)
+ assertThat(taskRepository.removeBoundsBeforeMaximize(task.taskId)).isEqualTo(bounds)
}
@Test
@@ -2557,7 +2671,7 @@
controller.toggleDesktopTaskSize(task)
// Assert last bounds before maximize removed after use
- assertThat(desktopModeTaskRepository.removeBoundsBeforeMaximize(task.taskId)).isNull()
+ assertThat(taskRepository.removeBoundsBeforeMaximize(task.taskId)).isNull()
}
private val desktopWallpaperIntent: Intent
@@ -2583,9 +2697,9 @@
val activityInfo = ActivityInfo()
task.topActivityInfo = activityInfo
whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task)
- desktopModeTaskRepository.addActiveTask(displayId, task.taskId)
- desktopModeTaskRepository.updateVisibleFreeformTasks(displayId, task.taskId, visible = true)
- desktopModeTaskRepository.addOrMoveFreeformTaskToTop(displayId, task.taskId)
+ taskRepository.addActiveTask(displayId, task.taskId)
+ taskRepository.updateTaskVisibility(displayId, task.taskId, visible = true)
+ taskRepository.addOrMoveFreeformTaskToTop(displayId, task.taskId)
runningTasks.add(task)
return task
}
@@ -2621,14 +2735,14 @@
screenOrientation == SCREEN_ORIENTATION_PORTRAIT) {
// Letterbox to portrait size
appCompatTaskInfo.topActivityBoundsLetterboxed = true
- appCompatTaskInfo.topActivityLetterboxWidth = 1200
- appCompatTaskInfo.topActivityLetterboxHeight = 1600
+ appCompatTaskInfo.topActivityLetterboxAppWidth = 1200
+ appCompatTaskInfo.topActivityLetterboxAppHeight = 1600
} else if (deviceOrientation == ORIENTATION_PORTRAIT &&
screenOrientation == SCREEN_ORIENTATION_LANDSCAPE) {
// Letterbox to landscape size
appCompatTaskInfo.topActivityBoundsLetterboxed = true
- appCompatTaskInfo.topActivityLetterboxWidth = 1600
- appCompatTaskInfo.topActivityLetterboxHeight = 1200
+ appCompatTaskInfo.topActivityLetterboxAppWidth = 1600
+ appCompatTaskInfo.topActivityLetterboxAppHeight = 1200
}
} else {
appCompatTaskInfo.topActivityBoundsLetterboxed = false
@@ -2678,12 +2792,12 @@
}
private fun markTaskVisible(task: RunningTaskInfo) {
- desktopModeTaskRepository.updateVisibleFreeformTasks(
+ taskRepository.updateTaskVisibility(
task.displayId, task.taskId, visible = true)
}
private fun markTaskHidden(task: RunningTaskInfo) {
- desktopModeTaskRepository.updateVisibleFreeformTasks(
+ taskRepository.updateTaskVisibility(
task.displayId, task.taskId, visible = false)
}
@@ -2704,11 +2818,14 @@
return arg.value
}
- private fun getLatestToggleResizeDesktopTaskWct(): WindowContainerTransaction {
+ private fun getLatestToggleResizeDesktopTaskWct(
+ currentBounds: Rect? = null
+ ): WindowContainerTransaction {
val arg: ArgumentCaptor<WindowContainerTransaction> =
ArgumentCaptor.forClass(WindowContainerTransaction::class.java)
if (ENABLE_SHELL_TRANSITIONS) {
- verify(toggleResizeDesktopTaskTransitionHandler, atLeastOnce()).startTransition(capture(arg))
+ verify(toggleResizeDesktopTaskTransitionHandler, atLeastOnce())
+ .startTransition(capture(arg), eq(currentBounds))
} else {
verify(shellTaskOrganizer).applyTransaction(capture(arg))
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt
index 70f3bf8..2d0e428 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt
@@ -30,6 +30,8 @@
import com.android.dx.mockito.inline.extended.ExtendedMockito
import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn
import com.android.dx.mockito.inline.extended.StaticMockitoSession
+import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_MINIMIZE_WINDOW
+import com.android.internal.jank.InteractionJankMonitor
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask
@@ -47,6 +49,8 @@
import org.mockito.Mock
import org.mockito.Mockito.any
import org.mockito.Mockito.`when`
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.verify
import org.mockito.quality.Strictness
@@ -65,6 +69,7 @@
@Mock lateinit var shellTaskOrganizer: ShellTaskOrganizer
@Mock lateinit var transitions: Transitions
+ @Mock lateinit var interactionJankMonitor: InteractionJankMonitor
private lateinit var mockitoSession: StaticMockitoSession
private lateinit var desktopTasksLimiter: DesktopTasksLimiter
@@ -79,7 +84,8 @@
desktopTaskRepo = DesktopModeTaskRepository()
desktopTasksLimiter =
- DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, MAX_TASK_LIMIT)
+ DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, MAX_TASK_LIMIT,
+ interactionJankMonitor, mContext)
}
@After
@@ -90,14 +96,16 @@
@Test
fun createDesktopTasksLimiter_withZeroLimit_shouldThrow() {
assertFailsWith<IllegalArgumentException> {
- DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, 0)
+ DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, 0,
+ interactionJankMonitor, mContext)
}
}
@Test
fun createDesktopTasksLimiter_withNegativeLimit_shouldThrow() {
assertFailsWith<IllegalArgumentException> {
- DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, -5)
+ DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, -5,
+ interactionJankMonitor, mContext)
}
}
@@ -325,7 +333,8 @@
@Test
fun getTaskToMinimizeIfNeeded_tasksAboveLimit_otherLimit_returnsBackTask() {
desktopTasksLimiter =
- DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, MAX_TASK_LIMIT2)
+ DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, MAX_TASK_LIMIT2,
+ interactionJankMonitor, mContext)
val tasks = (1..MAX_TASK_LIMIT2 + 1).map { setUpFreeformTask() }
val minimizedTask = desktopTasksLimiter.getTaskToMinimizeIfNeeded(
@@ -347,6 +356,91 @@
assertThat(minimizedTask).isEqualTo(tasks.last())
}
+ @Test
+ fun minimizeTransitionReadyAndFinished_logsJankInstrumentationBeginAndEnd() {
+ (1..<MAX_TASK_LIMIT).forEach { _ -> setUpFreeformTask() }
+ val transition = Binder()
+ val task = setUpFreeformTask()
+ desktopTasksLimiter.addPendingMinimizeChange(
+ transition, displayId = DEFAULT_DISPLAY, taskId = task.taskId)
+
+ desktopTasksLimiter.getTransitionObserver().onTransitionReady(
+ transition,
+ TransitionInfoBuilder(TRANSIT_OPEN).build(),
+ StubTransaction() /* startTransaction */,
+ StubTransaction() /* finishTransaction */)
+
+ desktopTasksLimiter.getTransitionObserver().onTransitionStarting(transition)
+
+ verify(interactionJankMonitor).begin(
+ any(),
+ eq(mContext),
+ eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW))
+
+ desktopTasksLimiter.getTransitionObserver().onTransitionFinished(
+ transition,
+ /* aborted = */ false)
+
+ verify(interactionJankMonitor).end(eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW))
+ }
+
+ @Test
+ fun minimizeTransitionReadyAndAborted_logsJankInstrumentationBeginAndCancel() {
+ (1..<MAX_TASK_LIMIT).forEach { _ -> setUpFreeformTask() }
+ val transition = Binder()
+ val task = setUpFreeformTask()
+ desktopTasksLimiter.addPendingMinimizeChange(
+ transition, displayId = DEFAULT_DISPLAY, taskId = task.taskId)
+
+ desktopTasksLimiter.getTransitionObserver().onTransitionReady(
+ transition,
+ TransitionInfoBuilder(TRANSIT_OPEN).build(),
+ StubTransaction() /* startTransaction */,
+ StubTransaction() /* finishTransaction */)
+
+ desktopTasksLimiter.getTransitionObserver().onTransitionStarting(transition)
+
+ verify(interactionJankMonitor).begin(
+ any(),
+ eq(mContext),
+ eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW))
+
+ desktopTasksLimiter.getTransitionObserver().onTransitionFinished(
+ transition,
+ /* aborted = */ true)
+
+ verify(interactionJankMonitor).cancel(eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW))
+ }
+
+ @Test
+ fun minimizeTransitionReadyAndMerged_logsJankInstrumentationBeginAndEnd() {
+ (1..<MAX_TASK_LIMIT).forEach { _ -> setUpFreeformTask() }
+ val mergedTransition = Binder()
+ val newTransition = Binder()
+ val task = setUpFreeformTask()
+ desktopTasksLimiter.addPendingMinimizeChange(
+ mergedTransition, displayId = DEFAULT_DISPLAY, taskId = task.taskId)
+
+ desktopTasksLimiter.getTransitionObserver().onTransitionReady(
+ mergedTransition,
+ TransitionInfoBuilder(TRANSIT_OPEN).build(),
+ StubTransaction() /* startTransaction */,
+ StubTransaction() /* finishTransaction */)
+
+ desktopTasksLimiter.getTransitionObserver().onTransitionStarting(mergedTransition)
+
+ verify(interactionJankMonitor).begin(
+ any(),
+ eq(mContext),
+ eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW))
+
+ desktopTasksLimiter.getTransitionObserver().onTransitionMerged(
+ mergedTransition,
+ newTransition)
+
+ verify(interactionJankMonitor).end(eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW))
+ }
+
private fun setUpFreeformTask(
displayId: Int = DEFAULT_DISPLAY,
): RunningTaskInfo {
@@ -358,7 +452,7 @@
}
private fun markTaskVisible(task: RunningTaskInfo) {
- desktopTaskRepo.updateVisibleFreeformTasks(
+ desktopTaskRepo.updateTaskVisibility(
task.displayId,
task.taskId,
visible = true
@@ -366,7 +460,7 @@
}
private fun markTaskHidden(task: RunningTaskInfo) {
- desktopTaskRepo.updateVisibleFreeformTasks(
+ desktopTaskRepo.updateTaskVisibility(
task.displayId,
task.taskId,
visible = false
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 eaef704..ff6c7ee 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
@@ -245,38 +245,6 @@
}
@Test
- public void testExitSplitScreen() {
- when(mMainStage.isActive()).thenReturn(true);
- mStageCoordinator.exitSplitScreen(INVALID_TASK_ID, EXIT_REASON_RETURN_HOME);
- verify(mSideStage).removeAllTasks(any(WindowContainerTransaction.class), eq(false));
- verify(mMainStage).deactivate(any(WindowContainerTransaction.class), eq(false));
- }
-
- @Test
- public void testExitSplitScreenToMainStage() {
- when(mMainStage.isActive()).thenReturn(true);
- final int testTaskId = 12345;
- when(mMainStage.containsTask(eq(testTaskId))).thenReturn(true);
- when(mSideStage.containsTask(eq(testTaskId))).thenReturn(false);
- mStageCoordinator.exitSplitScreen(testTaskId, EXIT_REASON_RETURN_HOME);
- verify(mMainStage).reorderChild(eq(testTaskId), eq(true),
- any(WindowContainerTransaction.class));
- verify(mMainStage).resetBounds(any(WindowContainerTransaction.class));
- }
-
- @Test
- public void testExitSplitScreenToSideStage() {
- when(mMainStage.isActive()).thenReturn(true);
- final int testTaskId = 12345;
- when(mMainStage.containsTask(eq(testTaskId))).thenReturn(false);
- when(mSideStage.containsTask(eq(testTaskId))).thenReturn(true);
- mStageCoordinator.exitSplitScreen(testTaskId, EXIT_REASON_RETURN_HOME);
- verify(mSideStage).reorderChild(eq(testTaskId), eq(true),
- any(WindowContainerTransaction.class));
- verify(mSideStage).resetBounds(any(WindowContainerTransaction.class));
- }
-
- @Test
public void testResolveStartStage_beforeSplitActivated_setsStagePosition() {
mStageCoordinator.setSideStagePosition(SPLIT_POSITION_TOP_OR_LEFT, null /* wct */);
@@ -367,12 +335,7 @@
mStageCoordinator.onFinishedWakingUp();
- if (Transitions.ENABLE_SHELL_TRANSITIONS) {
- verify(mTaskOrganizer).startNewTransition(eq(TRANSIT_SPLIT_DISMISS), notNull());
- } else {
- verify(mStageCoordinator).onSplitScreenExit();
- verify(mMainStage).deactivate(any(WindowContainerTransaction.class), eq(false));
- }
+ verify(mTaskOrganizer).startNewTransition(eq(TRANSIT_SPLIT_DISMISS), notNull());
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/CaptionWindowDecorationTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/CaptionWindowDecorationTests.kt
index 261d4b5..d141c2d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/CaptionWindowDecorationTests.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/CaptionWindowDecorationTests.kt
@@ -21,6 +21,7 @@
import android.content.ComponentName
import android.testing.AndroidTestingRunner
import android.view.Display
+import android.view.InsetsState
import android.view.WindowInsetsController
import androidx.test.filters.SmallTest
import com.android.wm.shell.ShellTestCase
@@ -45,7 +46,8 @@
relayoutParams,
taskInfo,
true,
- false
+ false,
+ InsetsState()
)
Truth.assertThat(relayoutParams.hasInputFeatureSpy()).isTrue()
@@ -63,7 +65,8 @@
relayoutParams,
taskInfo,
true,
- false
+ false,
+ InsetsState()
)
Truth.assertThat(relayoutParams.hasInputFeatureSpy()).isFalse()
@@ -77,7 +80,8 @@
relayoutParams,
taskInfo,
true,
- false
+ false,
+ InsetsState()
)
Truth.assertThat(relayoutParams.mOccludingCaptionElements.size).isEqualTo(2)
Truth.assertThat(relayoutParams.mOccludingCaptionElements[0].mAlignment).isEqualTo(
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
index 01c4f3a..68975ec 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
@@ -16,19 +16,23 @@
package com.android.wm.shell.windowdecor
import android.app.ActivityManager.RunningTaskInfo
-import android.app.WindowConfiguration
import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
import android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
+import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW
+import android.app.WindowConfiguration.WINDOWING_MODE_PINNED
import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED
+import android.app.WindowConfiguration.WindowingMode
import android.content.ComponentName
import android.content.Context
+import android.content.Intent
import android.content.pm.ActivityInfo
import android.graphics.Rect
import android.hardware.display.DisplayManager
import android.hardware.display.VirtualDisplay
import android.hardware.input.InputManager
+import android.net.Uri
import android.os.Handler
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
@@ -37,6 +41,7 @@
import android.platform.test.flag.junit.DeviceFlagsValueProvider
import android.platform.test.flag.junit.SetFlagsRule
import android.testing.AndroidTestingRunner
+import android.testing.TestableContext
import android.testing.TestableLooper.RunWithLooper
import android.util.SparseArray
import android.view.Choreographer
@@ -47,11 +52,13 @@
import android.view.InsetsSource
import android.view.InsetsState
import android.view.KeyEvent
+import android.view.Surface
import android.view.SurfaceControl
import android.view.SurfaceView
import android.view.View
import android.view.WindowInsets.Type.navigationBars
import android.view.WindowInsets.Type.statusBars
+import android.window.WindowContainerTransaction
import androidx.test.filters.SmallTest
import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
@@ -65,11 +72,14 @@
import com.android.wm.shell.TestRunningTaskInfoBuilder
import com.android.wm.shell.TestShellExecutor
import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser
+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.MultiInstanceHelper
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.common.SyncTransactionQueue
+import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource
import com.android.wm.shell.desktopmode.DesktopTasksController
import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter
@@ -81,13 +91,17 @@
import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModel.DesktopModeOnInsetsChangedListener
-import com.android.wm.shell.windowdecor.common.OnTaskActionClickListener
+import java.util.Optional
+import java.util.function.Consumer
+import java.util.function.Supplier
+import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentCaptor.forClass
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.anyInt
@@ -96,13 +110,16 @@
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.kotlin.any
+import org.mockito.kotlin.argThat
import org.mockito.kotlin.argumentCaptor
+import org.mockito.kotlin.doNothing
import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.whenever
import org.mockito.quality.Strictness
-import java.util.Optional
-import java.util.function.Supplier
+import junit.framework.Assert.assertFalse
+import junit.framework.Assert.assertTrue
/**
* Tests of [DesktopModeWindowDecorViewModel]
@@ -143,22 +160,36 @@
@Mock private lateinit var mockInteractionJankMonitor: InteractionJankMonitor
@Mock private lateinit var mockGenericLinksParser: AppToWebGenericLinksParser
private val bgExecutor = TestShellExecutor()
+ @Mock private lateinit var mockMultiInstanceHelper: MultiInstanceHelper
+ private lateinit var spyContext: TestableContext
private val transactionFactory = Supplier<SurfaceControl.Transaction> {
SurfaceControl.Transaction()
}
private val windowDecorByTaskIdSpy = spy(SparseArray<DesktopModeWindowDecoration>())
+ private lateinit var mockitoSession: StaticMockitoSession
private lateinit var shellInit: ShellInit
private lateinit var desktopModeOnInsetsChangedListener: DesktopModeOnInsetsChangedListener
+ private lateinit var displayChangingListener: DisplayChangeController.OnDisplayChangingListener
private lateinit var desktopModeWindowDecorViewModel: DesktopModeWindowDecorViewModel
@Before
fun setUp() {
+ mockitoSession =
+ mockitoSession()
+ .strictness(Strictness.LENIENT)
+ .spyStatic(DesktopModeStatus::class.java)
+ .spyStatic(DragPositioningCallbackUtility::class.java)
+ .startMocking()
+ doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(Mockito.any()) }
+
+ spyContext = spy(mContext)
+ doNothing().`when`(spyContext).startActivity(any())
shellInit = ShellInit(mockShellExecutor)
windowDecorByTaskIdSpy.clear()
desktopModeWindowDecorViewModel = DesktopModeWindowDecorViewModel(
- mContext,
+ spyContext,
mockShellExecutor,
mockMainHandler,
mockMainChoreographer,
@@ -174,6 +205,7 @@
mockTransitions,
Optional.of(mockDesktopTasksController),
mockGenericLinksParser,
+ mockMultiInstanceHelper,
mockDesktopModeWindowDecorFactory,
mockInputMonitorFactory,
transactionFactory,
@@ -193,10 +225,22 @@
shellInit.init()
- val listenerCaptor =
- argumentCaptor<DesktopModeWindowDecorViewModel.DesktopModeOnInsetsChangedListener>()
- verify(displayInsetsController).addInsetsChangedListener(anyInt(), listenerCaptor.capture())
- desktopModeOnInsetsChangedListener = listenerCaptor.firstValue
+ val insetListenerCaptor =
+ argumentCaptor<DesktopModeWindowDecorViewModel.DesktopModeOnInsetsChangedListener>()
+ verify(displayInsetsController)
+ .addInsetsChangedListener(anyInt(), insetListenerCaptor.capture())
+ desktopModeOnInsetsChangedListener = insetListenerCaptor.firstValue
+
+ val displayChangingListenerCaptor =
+ argumentCaptor<DisplayChangeController.OnDisplayChangingListener>()
+ verify(mockDisplayController)
+ .addDisplayChangingController(displayChangingListenerCaptor.capture())
+ displayChangingListener = displayChangingListenerCaptor.firstValue
+ }
+
+ @After
+ fun tearDown() {
+ mockitoSession.finishMocking()
}
@Test
@@ -206,25 +250,13 @@
val decoration = setUpMockDecorationForTask(task)
onTaskOpening(task, taskSurface)
+ assertTrue(windowDecorByTaskIdSpy.contains(task.taskId))
task.setWindowingMode(WINDOWING_MODE_UNDEFINED)
task.setActivityType(ACTIVITY_TYPE_UNDEFINED)
onTaskChanging(task, taskSurface)
- verify(mockDesktopModeWindowDecorFactory).create(
- mContext,
- mockDisplayController,
- mockSplitScreenController,
- mockTaskOrganizer,
- task,
- taskSurface,
- mockMainHandler,
- bgExecutor,
- mockMainChoreographer,
- mockSyncQueue,
- mockRootTaskDisplayAreaOrganizer,
- mockGenericLinksParser
- )
+ assertFalse(windowDecorByTaskIdSpy.contains(task.taskId))
verify(decoration).close()
}
@@ -238,38 +270,12 @@
setUpMockDecorationForTask(task)
onTaskChanging(task, taskSurface)
- verify(mockDesktopModeWindowDecorFactory, never()).create(
- mContext,
- mockDisplayController,
- mockSplitScreenController,
- mockTaskOrganizer,
- task,
- taskSurface,
- mockMainHandler,
- bgExecutor,
- mockMainChoreographer,
- mockSyncQueue,
- mockRootTaskDisplayAreaOrganizer,
- mockGenericLinksParser
- )
+ assertFalse(windowDecorByTaskIdSpy.contains(task.taskId))
task.setWindowingMode(WINDOWING_MODE_FREEFORM)
task.setActivityType(ACTIVITY_TYPE_STANDARD)
onTaskChanging(task, taskSurface)
- verify(mockDesktopModeWindowDecorFactory, times(1)).create(
- mContext,
- mockDisplayController,
- mockSplitScreenController,
- mockTaskOrganizer,
- task,
- taskSurface,
- mockMainHandler,
- bgExecutor,
- mockMainChoreographer,
- mockSyncQueue,
- mockRootTaskDisplayAreaOrganizer,
- mockGenericLinksParser
- )
+ assertTrue(windowDecorByTaskIdSpy.contains(task.taskId))
}
@Test
@@ -332,7 +338,7 @@
whenever(view.id).thenReturn(R.id.back_button)
val inputManager = mock(InputManager::class.java)
- mContext.addMockSystemService(InputManager::class.java, inputManager)
+ spyContext.addMockSystemService(InputManager::class.java, inputManager)
val freeformTaskTransitionStarter = mock(FreeformTaskTransitionStarter::class.java)
desktopModeWindowDecorViewModel
@@ -364,34 +370,22 @@
task.setWindowingMode(ACTIVITY_TYPE_UNDEFINED)
onTaskChanging(task)
- verify(mockDesktopModeWindowDecorFactory, never())
- .create(any(), any(), any(), any(), eq(task), any(), any(), any(), any(), any(),
- any(), any())
+ assertFalse(windowDecorByTaskIdSpy.contains(task.taskId))
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
fun testDecorationIsCreatedForTopTranslucentActivitiesWithStyleFloating() {
- val mockitoSession: StaticMockitoSession = mockitoSession()
- .strictness(Strictness.LENIENT)
- .spyStatic(DesktopModeStatus::class.java)
- .startMocking()
- try {
- val task = createTask(windowingMode = WINDOWING_MODE_FULLSCREEN, focused = true).apply {
- isTopActivityTransparent = true
- isTopActivityStyleFloating = true
- numActivities = 1
- }
- doReturn(true).`when` { DesktopModeStatus.canEnterDesktopMode(any()) }
- setUpMockDecorationsForTasks(task)
-
- onTaskOpening(task)
- verify(mockDesktopModeWindowDecorFactory)
- .create(any(), any(), any(), any(), eq(task), any(), any(), any(), any(),
- any(), any(), any())
- } finally {
- mockitoSession.finishMocking()
+ val task = createTask(windowingMode = WINDOWING_MODE_FULLSCREEN, focused = true).apply {
+ isTopActivityTransparent = true
+ isTopActivityStyleFloating = true
+ numActivities = 1
}
+ doReturn(true).`when` { DesktopModeStatus.canEnterDesktopMode(any()) }
+ setUpMockDecorationsForTasks(task)
+
+ onTaskOpening(task)
+ assertTrue(windowDecorByTaskIdSpy.contains(task.taskId))
}
@Test
@@ -404,9 +398,7 @@
}
onTaskOpening(task)
- verify(mockDesktopModeWindowDecorFactory, never())
- .create(any(), any(), any(), any(), eq(task), any(), any(), any(), any(), any(),
- any(), any())
+ assertFalse(windowDecorByTaskIdSpy.contains(task.taskId))
}
@Test
@@ -422,9 +414,7 @@
onTaskOpening(task)
- verify(mockDesktopModeWindowDecorFactory, never())
- .create(any(), any(), any(), any(), eq(task), any(), any(), any(), any(), any(),
- any(), any())
+ assertFalse(windowDecorByTaskIdSpy.contains(task.taskId))
}
@Test
@@ -507,102 +497,70 @@
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
fun testWindowDecor_desktopModeUnsupportedOnDevice_decorNotCreated() {
- val mockitoSession: StaticMockitoSession = mockitoSession()
- .strictness(Strictness.LENIENT)
- .spyStatic(DesktopModeStatus::class.java)
- .startMocking()
- try {
- // Simulate default enforce device restrictions system property
- whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(true)
+ // Simulate default enforce device restrictions system property
+ whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(true)
- val task = createTask(windowingMode = WINDOWING_MODE_FULLSCREEN, focused = true)
- // Simulate device that doesn't support desktop mode
- doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
+ val task = createTask(windowingMode = WINDOWING_MODE_FULLSCREEN, focused = true)
+ // Simulate device that doesn't support desktop mode
+ doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
- onTaskOpening(task)
- verify(mockDesktopModeWindowDecorFactory, never())
- .create(any(), any(), any(), any(), eq(task), any(), any(), any(), any(), any(),
- any(), any())
- } finally {
- mockitoSession.finishMocking()
- }
+ onTaskOpening(task)
+ assertFalse(windowDecorByTaskIdSpy.contains(task.taskId))
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
fun testWindowDecor_desktopModeUnsupportedOnDevice_deviceRestrictionsOverridden_decorCreated() {
- val mockitoSession: StaticMockitoSession = mockitoSession()
- .strictness(Strictness.LENIENT)
- .spyStatic(DesktopModeStatus::class.java)
- .startMocking()
- try {
- // Simulate enforce device restrictions system property overridden to false
- whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(false)
- // Simulate device that doesn't support desktop mode
- doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
+ // Simulate enforce device restrictions system property overridden to false
+ whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(false)
+ // Simulate device that doesn't support desktop mode
+ doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
- val task = createTask(windowingMode = WINDOWING_MODE_FULLSCREEN, focused = true)
- setUpMockDecorationsForTasks(task)
+ val task = createTask(windowingMode = WINDOWING_MODE_FULLSCREEN, focused = true)
+ setUpMockDecorationsForTasks(task)
- onTaskOpening(task)
- verify(mockDesktopModeWindowDecorFactory)
- .create(any(), any(), any(), any(), eq(task), any(), any(), any(), any(), any(),
- any(), any())
- } finally {
- mockitoSession.finishMocking()
- }
+ onTaskOpening(task)
+ assertTrue(windowDecorByTaskIdSpy.contains(task.taskId))
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
fun testWindowDecor_deviceSupportsDesktopMode_decorCreated() {
- val mockitoSession: StaticMockitoSession = mockitoSession()
- .strictness(Strictness.LENIENT)
- .spyStatic(DesktopModeStatus::class.java)
- .startMocking()
- try {
- // Simulate default enforce device restrictions system property
- whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(true)
+ // Simulate default enforce device restrictions system property
+ whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(true)
- val task = createTask(windowingMode = WINDOWING_MODE_FULLSCREEN, focused = true)
- doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
- setUpMockDecorationsForTasks(task)
+ val task = createTask(windowingMode = WINDOWING_MODE_FULLSCREEN, focused = true)
+ doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
+ setUpMockDecorationsForTasks(task)
- onTaskOpening(task)
- verify(mockDesktopModeWindowDecorFactory)
- .create(any(), any(), any(), any(), eq(task), any(), any(), any(), any(), any(),
- any(), any())
- } finally {
- mockitoSession.finishMocking()
- }
+ onTaskOpening(task)
+ assertTrue(windowDecorByTaskIdSpy.contains(task.taskId))
}
@Test
fun testOnDecorMaximizedOrRestored_togglesTaskSize() {
- val decor = setUpMockDecorationForTask(createTask(windowingMode = WINDOWING_MODE_FREEFORM))
- onTaskOpening(decor.mTaskInfo)
- val maxOrRestoreListener = ArgumentCaptor.forClass(OnTaskActionClickListener::class.java)
- .let { captor ->
- verify(decor).setOnMaximizeOrRestoreClickListener(captor.capture())
- return@let captor.value
- }
+ val maxOrRestoreListenerCaptor = forClass(Function0::class.java)
+ as ArgumentCaptor<Function0<Unit>>
+ val decor = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FREEFORM,
+ onMaxOrRestoreListenerCaptor = maxOrRestoreListenerCaptor
+ )
- maxOrRestoreListener.onClick(decor.mTaskInfo.taskId, "test")
+ maxOrRestoreListenerCaptor.value.invoke()
verify(mockDesktopTasksController).toggleDesktopTaskSize(decor.mTaskInfo)
}
@Test
fun testOnDecorMaximizedOrRestored_closesMenus() {
- val decor = setUpMockDecorationForTask(createTask(windowingMode = WINDOWING_MODE_FREEFORM))
- onTaskOpening(decor.mTaskInfo)
- val maxOrRestoreListener = ArgumentCaptor.forClass(OnTaskActionClickListener::class.java)
- .let { captor ->
- verify(decor).setOnMaximizeOrRestoreClickListener(captor.capture())
- return@let captor.value
- }
+ val maxOrRestoreListenerCaptor = forClass(Function0::class.java)
+ as ArgumentCaptor<Function0<Unit>>
+ val decor = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FREEFORM,
+ onMaxOrRestoreListenerCaptor = maxOrRestoreListenerCaptor
+ )
- maxOrRestoreListener.onClick(decor.mTaskInfo.taskId, "test")
+ maxOrRestoreListenerCaptor.value.invoke()
verify(decor).closeHandleMenu()
verify(decor).closeMaximizeMenu()
@@ -610,66 +568,464 @@
@Test
fun testOnDecorSnappedLeft_snapResizes() {
- val decor = setUpMockDecorationForTask(createTask(windowingMode = WINDOWING_MODE_FREEFORM))
- onTaskOpening(decor.mTaskInfo)
- val snapLeftListener = ArgumentCaptor.forClass(OnTaskActionClickListener::class.java)
- .let { captor ->
- verify(decor).setOnLeftSnapClickListener(captor.capture())
- return@let captor.value
- }
+ val onLeftSnapClickListenerCaptor = forClass(Function0::class.java)
+ as ArgumentCaptor<Function0<Unit>>
+ val decor = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FREEFORM,
+ onLeftSnapClickListenerCaptor = onLeftSnapClickListenerCaptor
+ )
- snapLeftListener.onClick(decor.mTaskInfo.taskId, "test")
+ val currentBounds = decor.mTaskInfo.configuration.windowConfiguration.bounds
+ onLeftSnapClickListenerCaptor.value.invoke()
- verify(mockDesktopTasksController).snapToHalfScreen(decor.mTaskInfo, SnapPosition.LEFT)
+ verify(mockDesktopTasksController)
+ .snapToHalfScreen(decor.mTaskInfo, currentBounds, SnapPosition.LEFT)
}
@Test
fun testOnDecorSnappedLeft_closeMenus() {
- val decor = setUpMockDecorationForTask(createTask(windowingMode = WINDOWING_MODE_FREEFORM))
- onTaskOpening(decor.mTaskInfo)
- val snapLeftListener = ArgumentCaptor.forClass(OnTaskActionClickListener::class.java)
- .let { captor ->
- verify(decor).setOnLeftSnapClickListener(captor.capture())
- return@let captor.value
- }
+ val onLeftSnapClickListenerCaptor = forClass(Function0::class.java)
+ as ArgumentCaptor<Function0<Unit>>
+ val decor = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FREEFORM,
+ onLeftSnapClickListenerCaptor = onLeftSnapClickListenerCaptor
+ )
- snapLeftListener.onClick(decor.mTaskInfo.taskId, "test")
+ onLeftSnapClickListenerCaptor.value.invoke()
verify(decor).closeHandleMenu()
verify(decor).closeMaximizeMenu()
}
@Test
+ @DisableFlags(Flags.FLAG_DISABLE_NON_RESIZABLE_APP_SNAP_RESIZING)
+ fun testOnSnapResizeLeft_nonResizable_decorSnappedLeft() {
+ val onLeftSnapClickListenerCaptor = forClass(Function0::class.java)
+ as ArgumentCaptor<Function0<Unit>>
+ val decor = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FREEFORM,
+ onLeftSnapClickListenerCaptor = onLeftSnapClickListenerCaptor
+ ).also { it.mTaskInfo.isResizeable = false }
+
+ val currentBounds = decor.mTaskInfo.configuration.windowConfiguration.bounds
+ onLeftSnapClickListenerCaptor.value.invoke()
+
+ verify(mockDesktopTasksController)
+ .snapToHalfScreen(decor.mTaskInfo, currentBounds, SnapPosition.LEFT)
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_DISABLE_NON_RESIZABLE_APP_SNAP_RESIZING)
+ fun testOnSnapResizeLeft_nonResizable_decorNotSnapped() {
+ val onLeftSnapClickListenerCaptor = forClass(Function0::class.java)
+ as ArgumentCaptor<Function0<Unit>>
+ val decor = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FREEFORM,
+ onLeftSnapClickListenerCaptor = onLeftSnapClickListenerCaptor
+ ).also { it.mTaskInfo.isResizeable = false }
+
+ val currentBounds = decor.mTaskInfo.configuration.windowConfiguration.bounds
+ onLeftSnapClickListenerCaptor.value.invoke()
+
+ verify(mockDesktopTasksController, never())
+ .snapToHalfScreen(decor.mTaskInfo, currentBounds, SnapPosition.LEFT)
+ }
+
+ @Test
fun testOnDecorSnappedRight_snapResizes() {
- val decor = setUpMockDecorationForTask(createTask(windowingMode = WINDOWING_MODE_FREEFORM))
- onTaskOpening(decor.mTaskInfo)
- val snapLeftListener = ArgumentCaptor.forClass(OnTaskActionClickListener::class.java)
- .let { captor ->
- verify(decor).setOnRightSnapClickListener(captor.capture())
- return@let captor.value
- }
+ val onRightSnapClickListenerCaptor = forClass(Function0::class.java)
+ as ArgumentCaptor<Function0<Unit>>
+ val decor = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FREEFORM,
+ onRightSnapClickListenerCaptor = onRightSnapClickListenerCaptor
+ )
- snapLeftListener.onClick(decor.mTaskInfo.taskId, "test")
+ val currentBounds = decor.mTaskInfo.configuration.windowConfiguration.bounds
+ onRightSnapClickListenerCaptor.value.invoke()
- verify(mockDesktopTasksController).snapToHalfScreen(decor.mTaskInfo, SnapPosition.RIGHT)
+ verify(mockDesktopTasksController)
+ .snapToHalfScreen(decor.mTaskInfo, currentBounds, SnapPosition.RIGHT)
}
@Test
fun testOnDecorSnappedRight_closeMenus() {
- val decor = setUpMockDecorationForTask(createTask(windowingMode = WINDOWING_MODE_FREEFORM))
- onTaskOpening(decor.mTaskInfo)
- val snapLeftListener = ArgumentCaptor.forClass(OnTaskActionClickListener::class.java)
- .let { captor ->
- verify(decor).setOnRightSnapClickListener(captor.capture())
- return@let captor.value
- }
+ val onRightSnapClickListenerCaptor = forClass(Function0::class.java)
+ as ArgumentCaptor<Function0<Unit>>
+ val decor = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FREEFORM,
+ onRightSnapClickListenerCaptor = onRightSnapClickListenerCaptor
+ )
- snapLeftListener.onClick(decor.mTaskInfo.taskId, "test")
+ onRightSnapClickListenerCaptor.value.invoke()
verify(decor).closeHandleMenu()
verify(decor).closeMaximizeMenu()
}
+ @Test
+ @DisableFlags(Flags.FLAG_DISABLE_NON_RESIZABLE_APP_SNAP_RESIZING)
+ fun testOnSnapResizeRight_nonResizable_decorSnappedRight() {
+ val onRightSnapClickListenerCaptor = forClass(Function0::class.java)
+ as ArgumentCaptor<Function0<Unit>>
+ val decor = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FREEFORM,
+ onRightSnapClickListenerCaptor = onRightSnapClickListenerCaptor
+ ).also { it.mTaskInfo.isResizeable = false }
+
+ val currentBounds = decor.mTaskInfo.configuration.windowConfiguration.bounds
+ onRightSnapClickListenerCaptor.value.invoke()
+
+ verify(mockDesktopTasksController)
+ .snapToHalfScreen(decor.mTaskInfo, currentBounds, SnapPosition.RIGHT)
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_DISABLE_NON_RESIZABLE_APP_SNAP_RESIZING)
+ fun testOnSnapResizeRight_nonResizable_decorNotSnapped() {
+ val onRightSnapClickListenerCaptor = forClass(Function0::class.java)
+ as ArgumentCaptor<Function0<Unit>>
+ val decor = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FREEFORM,
+ onRightSnapClickListenerCaptor = onRightSnapClickListenerCaptor
+ ).also { it.mTaskInfo.isResizeable = false }
+
+ val currentBounds = decor.mTaskInfo.configuration.windowConfiguration.bounds
+ onRightSnapClickListenerCaptor.value.invoke()
+
+ verify(mockDesktopTasksController, never())
+ .snapToHalfScreen(decor.mTaskInfo, currentBounds, SnapPosition.RIGHT)
+ }
+
+ @Test
+ fun testDecor_onClickToDesktop_movesToDesktopWithSource() {
+ val toDesktopListenerCaptor = forClass(Consumer::class.java)
+ as ArgumentCaptor<Consumer<DesktopModeTransitionSource>>
+ val decor = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FULLSCREEN,
+ onToDesktopClickListenerCaptor = toDesktopListenerCaptor
+ )
+
+ toDesktopListenerCaptor.value.accept(DesktopModeTransitionSource.APP_HANDLE_MENU_BUTTON)
+
+ verify(mockDesktopTasksController).moveTaskToDesktop(
+ eq(decor.mTaskInfo.taskId),
+ any(),
+ eq(DesktopModeTransitionSource.APP_HANDLE_MENU_BUTTON)
+ )
+ }
+
+ @Test
+ fun testDecor_onClickToDesktop_addsCaptionInsets() {
+ val toDesktopListenerCaptor = forClass(Consumer::class.java)
+ as ArgumentCaptor<Consumer<DesktopModeTransitionSource>>
+ val decor = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FULLSCREEN,
+ onToDesktopClickListenerCaptor = toDesktopListenerCaptor
+ )
+
+ toDesktopListenerCaptor.value.accept(DesktopModeTransitionSource.APP_HANDLE_MENU_BUTTON)
+
+ verify(decor).addCaptionInset(any())
+ }
+
+ @Test
+ fun testDecor_onClickToDesktop_closesHandleMenu() {
+ val toDesktopListenerCaptor = forClass(Consumer::class.java)
+ as ArgumentCaptor<Consumer<DesktopModeTransitionSource>>
+ val decor = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FULLSCREEN,
+ onToDesktopClickListenerCaptor = toDesktopListenerCaptor
+ )
+
+ toDesktopListenerCaptor.value.accept(DesktopModeTransitionSource.APP_HANDLE_MENU_BUTTON)
+
+ verify(decor).closeHandleMenu()
+ }
+
+ @Test
+ fun testDecor_onClickToFullscreen_closesHandleMenu() {
+ val toFullscreenListenerCaptor = forClass(Function0::class.java)
+ as ArgumentCaptor<Function0<Unit>>
+ val decor = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FREEFORM,
+ onToFullscreenClickListenerCaptor = toFullscreenListenerCaptor
+ )
+
+ toFullscreenListenerCaptor.value.invoke()
+
+ verify(decor).closeHandleMenu()
+ }
+
+ @Test
+ fun testDecor_onClickToFullscreen_isFreeform_movesToFullscreen() {
+ val toFullscreenListenerCaptor = forClass(Function0::class.java)
+ as ArgumentCaptor<Function0<Unit>>
+ val decor = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FREEFORM,
+ onToFullscreenClickListenerCaptor = toFullscreenListenerCaptor
+ )
+
+ toFullscreenListenerCaptor.value.invoke()
+
+ verify(mockDesktopTasksController).moveToFullscreen(
+ decor.mTaskInfo.taskId,
+ DesktopModeTransitionSource.APP_HANDLE_MENU_BUTTON
+ )
+ }
+
+ @Test
+ fun testDecor_onClickToFullscreen_isSplit_movesToFullscreen() {
+ val toFullscreenListenerCaptor = forClass(Function0::class.java)
+ as ArgumentCaptor<Function0<Unit>>
+ val decor = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_MULTI_WINDOW,
+ onToFullscreenClickListenerCaptor = toFullscreenListenerCaptor
+ )
+
+ toFullscreenListenerCaptor.value.invoke()
+
+ verify(mockSplitScreenController).moveTaskToFullscreen(
+ decor.mTaskInfo.taskId,
+ SplitScreenController.EXIT_REASON_DESKTOP_MODE
+ )
+ }
+
+ @Test
+ fun testDecor_onClickToSplitScreen_closesHandleMenu() {
+ val toSplitScreenListenerCaptor = forClass(Function0::class.java)
+ as ArgumentCaptor<Function0<Unit>>
+ val decor = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_MULTI_WINDOW,
+ onToSplitScreenClickListenerCaptor = toSplitScreenListenerCaptor
+ )
+
+ toSplitScreenListenerCaptor.value.invoke()
+
+ verify(decor).closeHandleMenu()
+ }
+
+ @Test
+ fun testDecor_onClickToSplitScreen_requestsSplit() {
+ val toSplitScreenListenerCaptor = forClass(Function0::class.java)
+ as ArgumentCaptor<Function0<Unit>>
+ val decor = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_MULTI_WINDOW,
+ onToSplitScreenClickListenerCaptor = toSplitScreenListenerCaptor
+ )
+
+ toSplitScreenListenerCaptor.value.invoke()
+
+ verify(mockDesktopTasksController).requestSplit(decor.mTaskInfo, leftOrTop = false)
+ }
+
+ @Test
+ fun testDecor_onClickToSplitScreen_disposesStatusBarInputLayer() {
+ val toSplitScreenListenerCaptor = forClass(Function0::class.java)
+ as ArgumentCaptor<Function0<Unit>>
+ val decor = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_MULTI_WINDOW,
+ onToSplitScreenClickListenerCaptor = toSplitScreenListenerCaptor
+ )
+
+ toSplitScreenListenerCaptor.value.invoke()
+
+ verify(decor).disposeStatusBarInputLayer()
+ }
+
+ @Test
+ fun testDecor_onClickToOpenBrowser_closeMenus() {
+ val openInBrowserListenerCaptor = forClass(Consumer::class.java)
+ as ArgumentCaptor<Consumer<Uri>>
+ val decor = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FULLSCREEN,
+ onOpenInBrowserClickListener = openInBrowserListenerCaptor
+ )
+
+ openInBrowserListenerCaptor.value.accept(Uri.EMPTY)
+
+ verify(decor).closeHandleMenu()
+ verify(decor).closeMaximizeMenu()
+ }
+
+ @Test
+ fun testDecor_onClickToOpenBrowser_opensBrowser() {
+ doNothing().whenever(spyContext).startActivity(any())
+ val uri = Uri.parse("https://www.google.com")
+ val openInBrowserListenerCaptor = forClass(Consumer::class.java)
+ as ArgumentCaptor<Consumer<Uri>>
+ createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FULLSCREEN,
+ onOpenInBrowserClickListener = openInBrowserListenerCaptor
+ )
+
+ openInBrowserListenerCaptor.value.accept(uri)
+
+ verify(spyContext).startActivity(argThat { intent ->
+ intent.data == uri
+ && ((intent.flags and Intent.FLAG_ACTIVITY_NEW_TASK) != 0)
+ && intent.categories.contains(Intent.CATEGORY_LAUNCHER)
+ && intent.action == Intent.ACTION_MAIN
+ })
+ }
+
+ @Test
+ fun testOnDisplayRotation_tasksOutOfValidArea_taskBoundsUpdated() {
+ val task = createTask(focused = true, windowingMode = WINDOWING_MODE_FREEFORM)
+ val secondTask =
+ createTask(displayId = task.displayId, windowingMode = WINDOWING_MODE_FREEFORM)
+ val thirdTask =
+ createTask(displayId = task.displayId, windowingMode = WINDOWING_MODE_FREEFORM)
+
+ doReturn(true).`when` {
+ DragPositioningCallbackUtility.snapTaskBoundsIfNecessary(any(), any())
+ }
+ setUpMockDecorationsForTasks(task, secondTask, thirdTask)
+
+ onTaskOpening(task)
+ onTaskOpening(secondTask)
+ onTaskOpening(thirdTask)
+
+ val wct = mock<WindowContainerTransaction>()
+
+ displayChangingListener.onDisplayChange(
+ task.displayId, Surface.ROTATION_0, Surface.ROTATION_90, null, wct
+ )
+
+ verify(wct).setBounds(eq(task.token), any())
+ verify(wct).setBounds(eq(secondTask.token), any())
+ verify(wct).setBounds(eq(thirdTask.token), any())
+ }
+
+ @Test
+ fun testOnDisplayRotation_taskInValidArea_taskBoundsNotUpdated() {
+ val task = createTask(focused = true, windowingMode = WINDOWING_MODE_FREEFORM)
+ val secondTask =
+ createTask(displayId = task.displayId, windowingMode = WINDOWING_MODE_FREEFORM)
+ val thirdTask =
+ createTask(displayId = task.displayId, windowingMode = WINDOWING_MODE_FREEFORM)
+
+ doReturn(false).`when` {
+ DragPositioningCallbackUtility.snapTaskBoundsIfNecessary(any(), any())
+ }
+ setUpMockDecorationsForTasks(task, secondTask, thirdTask)
+
+ onTaskOpening(task)
+ onTaskOpening(secondTask)
+ onTaskOpening(thirdTask)
+
+ val wct = mock<WindowContainerTransaction>()
+ displayChangingListener.onDisplayChange(
+ task.displayId, Surface.ROTATION_0, Surface.ROTATION_90, null, wct
+ )
+
+ verify(wct, never()).setBounds(eq(task.token), any())
+ verify(wct, never()).setBounds(eq(secondTask.token), any())
+ verify(wct, never()).setBounds(eq(thirdTask.token), any())
+ }
+
+ @Test
+ fun testOnDisplayRotation_sameOrientationRotation_taskBoundsNotUpdated() {
+ val task = createTask(focused = true, windowingMode = WINDOWING_MODE_FREEFORM)
+ val secondTask =
+ createTask(displayId = task.displayId, windowingMode = WINDOWING_MODE_FREEFORM)
+ val thirdTask =
+ createTask(displayId = task.displayId, windowingMode = WINDOWING_MODE_FREEFORM)
+
+ setUpMockDecorationsForTasks(task, secondTask, thirdTask)
+
+ onTaskOpening(task)
+ onTaskOpening(secondTask)
+ onTaskOpening(thirdTask)
+
+ val wct = mock<WindowContainerTransaction>()
+ displayChangingListener.onDisplayChange(
+ task.displayId, Surface.ROTATION_0, Surface.ROTATION_180, null, wct
+ )
+
+ verify(wct, never()).setBounds(eq(task.token), any())
+ verify(wct, never()).setBounds(eq(secondTask.token), any())
+ verify(wct, never()).setBounds(eq(thirdTask.token), any())
+ }
+
+ @Test
+ fun testOnDisplayRotation_differentDisplayId_taskBoundsNotUpdated() {
+ val task = createTask(focused = true, windowingMode = WINDOWING_MODE_FREEFORM)
+ val secondTask = createTask(displayId = -2, windowingMode = WINDOWING_MODE_FREEFORM)
+ val thirdTask = createTask(displayId = -3, windowingMode = WINDOWING_MODE_FREEFORM)
+
+ doReturn(true).`when` {
+ DragPositioningCallbackUtility.snapTaskBoundsIfNecessary(any(), any())
+ }
+ setUpMockDecorationsForTasks(task, secondTask, thirdTask)
+
+ onTaskOpening(task)
+ onTaskOpening(secondTask)
+ onTaskOpening(thirdTask)
+
+ val wct = mock<WindowContainerTransaction>()
+ displayChangingListener.onDisplayChange(
+ task.displayId, Surface.ROTATION_0, Surface.ROTATION_90, null, wct
+ )
+
+ verify(wct).setBounds(eq(task.token), any())
+ verify(wct, never()).setBounds(eq(secondTask.token), any())
+ verify(wct, never()).setBounds(eq(thirdTask.token), any())
+ }
+
+ @Test
+ fun testOnDisplayRotation_nonFreeformTask_taskBoundsNotUpdated() {
+ val task = createTask(focused = true, windowingMode = WINDOWING_MODE_FREEFORM)
+ val secondTask = createTask(displayId = -2, windowingMode = WINDOWING_MODE_FULLSCREEN)
+ val thirdTask = createTask(displayId = -3, windowingMode = WINDOWING_MODE_PINNED)
+
+ doReturn(true).`when` {
+ DragPositioningCallbackUtility.snapTaskBoundsIfNecessary(any(), any())
+ }
+ setUpMockDecorationsForTasks(task, secondTask, thirdTask)
+
+ onTaskOpening(task)
+ onTaskOpening(secondTask)
+ onTaskOpening(thirdTask)
+
+ val wct = mock<WindowContainerTransaction>()
+ displayChangingListener.onDisplayChange(
+ task.displayId, Surface.ROTATION_0, Surface.ROTATION_90, null, wct
+ )
+
+ verify(wct).setBounds(eq(task.token), any())
+ verify(wct, never()).setBounds(eq(secondTask.token), any())
+ verify(wct, never()).setBounds(eq(thirdTask.token), any())
+ }
+
+ private fun createOpenTaskDecoration(
+ @WindowingMode windowingMode: Int,
+ onMaxOrRestoreListenerCaptor: ArgumentCaptor<Function0<Unit>> =
+ forClass(Function0::class.java) as ArgumentCaptor<Function0<Unit>>,
+ onLeftSnapClickListenerCaptor: ArgumentCaptor<Function0<Unit>> =
+ forClass(Function0::class.java) as ArgumentCaptor<Function0<Unit>>,
+ onRightSnapClickListenerCaptor: ArgumentCaptor<Function0<Unit>> =
+ forClass(Function0::class.java) as ArgumentCaptor<Function0<Unit>>,
+ onToDesktopClickListenerCaptor: ArgumentCaptor<Consumer<DesktopModeTransitionSource>> =
+ forClass(Consumer::class.java) as ArgumentCaptor<Consumer<DesktopModeTransitionSource>>,
+ onToFullscreenClickListenerCaptor: ArgumentCaptor<Function0<Unit>> =
+ forClass(Function0::class.java) as ArgumentCaptor<Function0<Unit>>,
+ onToSplitScreenClickListenerCaptor: ArgumentCaptor<Function0<Unit>> =
+ forClass(Function0::class.java) as ArgumentCaptor<Function0<Unit>>,
+ onOpenInBrowserClickListener: ArgumentCaptor<Consumer<Uri>> =
+ forClass(Consumer::class.java) as ArgumentCaptor<Consumer<Uri>>,
+ ): DesktopModeWindowDecoration {
+ val decor = setUpMockDecorationForTask(createTask(windowingMode = windowingMode))
+ onTaskOpening(decor.mTaskInfo)
+ verify(decor).setOnMaximizeOrRestoreClickListener(onMaxOrRestoreListenerCaptor.capture())
+ verify(decor).setOnLeftSnapClickListener(onLeftSnapClickListenerCaptor.capture())
+ verify(decor).setOnRightSnapClickListener(onRightSnapClickListenerCaptor.capture())
+ verify(decor).setOnToDesktopClickListener(onToDesktopClickListenerCaptor.capture())
+ verify(decor).setOnToFullscreenClickListener(onToFullscreenClickListenerCaptor.capture())
+ verify(decor).setOnToSplitScreenClickListener(onToSplitScreenClickListenerCaptor.capture())
+ verify(decor).setOpenInBrowserClickListener(onOpenInBrowserClickListener.capture())
+ return decor
+ }
+
private fun onTaskOpening(task: RunningTaskInfo, leash: SurfaceControl = SurfaceControl()) {
desktopModeWindowDecorViewModel.onTaskOpening(
task,
@@ -690,10 +1046,10 @@
private fun createTask(
displayId: Int = DEFAULT_DISPLAY,
- @WindowConfiguration.WindowingMode windowingMode: Int,
+ @WindowingMode windowingMode: Int,
activityType: Int = ACTIVITY_TYPE_STANDARD,
focused: Boolean = true,
- activityInfo: ActivityInfo = ActivityInfo()
+ activityInfo: ActivityInfo = ActivityInfo(),
): RunningTaskInfo {
return TestRunningTaskInfoBuilder()
.setDisplayId(displayId)
@@ -703,17 +1059,24 @@
.build().apply {
topActivityInfo = activityInfo
isFocused = focused
+ isResizeable = true
}
}
private fun setUpMockDecorationForTask(task: RunningTaskInfo): DesktopModeWindowDecoration {
val decoration = mock(DesktopModeWindowDecoration::class.java)
whenever(
- mockDesktopModeWindowDecorFactory.create(any(), any(), any(), any(), eq(task), any(),
- any(), any(), any(), any(), any(), any())
+ mockDesktopModeWindowDecorFactory.create(
+ any(), any(), any(), any(), any(), eq(task), any(), any(), any(), any(), any(),
+ any(), any(), any())
).thenReturn(decoration)
decoration.mTaskInfo = task
whenever(decoration.isFocused).thenReturn(task.isFocused)
+ if (task.windowingMode == WINDOWING_MODE_MULTI_WINDOW) {
+ whenever(mockSplitScreenController.isTaskInSplitScreen(task.taskId))
+ .thenReturn(true)
+ }
+ whenever(decoration.calculateValidDragArea()).thenReturn(Rect(0, 60, 2560, 1600))
return decoration
}
@@ -734,7 +1097,7 @@
)
}
- private fun RunningTaskInfo.setWindowingMode(@WindowConfiguration.WindowingMode mode: Int) {
+ private fun RunningTaskInfo.setWindowingMode(@WindowingMode mode: Int) {
configuration.windowConfiguration.windowingMode = mode
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
index cee9307..596adfb 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
@@ -89,14 +89,15 @@
import com.android.wm.shell.TestShellExecutor;
import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser;
import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.MultiInstanceHelper;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.windowdecor.WindowDecoration.RelayoutParams;
-import com.android.wm.shell.windowdecor.common.OnTaskActionClickListener;
import kotlin.Unit;
+import kotlin.jvm.functions.Function0;
import kotlin.jvm.functions.Function1;
import org.junit.After;
@@ -110,6 +111,7 @@
import org.mockito.Mock;
import org.mockito.quality.Strictness;
+import java.util.function.Consumer;
import java.util.function.Supplier;
/**
@@ -167,13 +169,14 @@
@Mock
private Handler mMockHandler;
@Mock
- private DesktopModeWindowDecoration.OpenInBrowserClickListener mMockOpenInBrowserClickListener;
+ private Consumer<Uri> mMockOpenInBrowserClickListener;
@Mock
private AppToWebGenericLinksParser mMockGenericLinksParser;
@Mock
private HandleMenu mMockHandleMenu;
@Mock
private HandleMenuFactory mMockHandleMenuFactory;
+ private MultiInstanceHelper mMockMultiInstanceHelper;
@Captor
private ArgumentCaptor<Function1<Boolean, Unit>> mOnMaxMenuHoverChangeListener;
@Captor
@@ -217,8 +220,9 @@
final Display defaultDisplay = mock(Display.class);
doReturn(defaultDisplay).when(mMockDisplayController).getDisplay(Display.DEFAULT_DISPLAY);
doReturn(mInsetsState).when(mMockDisplayController).getInsetsState(anyInt());
- doReturn(mMockHandleMenu).when(mMockHandleMenuFactory).create(any(), anyInt(), any(), any(),
- any(), any(), any(), any(), anyBoolean(), any(), anyInt(), anyInt(), anyInt());
+ when(mMockHandleMenuFactory.create(any(), anyInt(), any(), any(),
+ any(), anyBoolean(), anyBoolean(), any(), anyInt(), anyInt(), anyInt()))
+ .thenReturn(mMockHandleMenu);
}
@After
@@ -739,9 +743,21 @@
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(true /* visible */);
final DesktopModeWindowDecoration decor = createWindowDecoration(
taskInfo, TEST_URI1 /* captured link */, null /* generic link */);
+ final ArgumentCaptor<Function1<Uri, Unit>> openInBrowserCaptor =
+ ArgumentCaptor.forClass(Function1.class);
+
// Simulate menu opening and clicking open in browser button
decor.createHandleMenu(mMockSplitScreenController);
- decor.onOpenInBrowserClick();
+ verify(mMockHandleMenu).show(
+ any(),
+ any(),
+ any(),
+ any(),
+ openInBrowserCaptor.capture(),
+ any(),
+ any()
+ );
+ openInBrowserCaptor.getValue().invoke(TEST_URI1);
// Verify handle menu's browser link not set to captured link since link not valid after
// open in browser clicked
@@ -755,10 +771,22 @@
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(true /* visible */);
final DesktopModeWindowDecoration decor = createWindowDecoration(
taskInfo, TEST_URI1 /* captured link */, null /* generic link */);
+ final ArgumentCaptor<Function1<Uri, Unit>> openInBrowserCaptor =
+ ArgumentCaptor.forClass(Function1.class);
decor.createHandleMenu(mMockSplitScreenController);
- decor.onOpenInBrowserClick();
+ verify(mMockHandleMenu).show(
+ any(),
+ any(),
+ any(),
+ any(),
+ openInBrowserCaptor.capture(),
+ any(),
+ any()
+ );
- verify(mMockOpenInBrowserClickListener).onClick(any(), any());
+ openInBrowserCaptor.getValue().invoke(TEST_URI1);
+
+ verify(mMockOpenInBrowserClickListener).accept(TEST_URI1);
}
@Test
@@ -773,13 +801,37 @@
verifyHandleMenuCreated(TEST_URI2);
}
+ @Test
+ public void handleMenu_onCloseMenuClick_closesMenu() {
+ final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
+ final DesktopModeWindowDecoration decoration = createWindowDecoration(taskInfo,
+ true /* relayout */);
+ final ArgumentCaptor<Function0<Unit>> closeClickListener =
+ ArgumentCaptor.forClass(Function0.class);
+ decoration.createHandleMenu(mMockSplitScreenController);
+ verify(mMockHandleMenu).show(
+ any(),
+ any(),
+ any(),
+ any(),
+ any(),
+ closeClickListener.capture(),
+ any()
+ );
+
+ closeClickListener.getValue().invoke();
+
+ verify(mMockHandleMenu).close();
+ assertFalse(decoration.isHandleMenuActive());
+ }
+
private void verifyHandleMenuCreated(@Nullable Uri uri) {
- verify(mMockHandleMenuFactory).create(any(), anyInt(), any(), any(), any(), any(), any(),
- any(), anyBoolean(), eq(uri), anyInt(), anyInt(), anyInt());
+ verify(mMockHandleMenuFactory).create(any(), anyInt(), any(), any(),
+ any(), anyBoolean(), anyBoolean(), eq(uri), anyInt(), anyInt(), anyInt());
}
private void createMaximizeMenu(DesktopModeWindowDecoration decoration, MaximizeMenu menu) {
- final OnTaskActionClickListener l = (taskId, tag) -> {};
+ final Function0<Unit> l = () -> Unit.INSTANCE;
decoration.setOnMaximizeOrRestoreClickListener(l);
decoration.setOnLeftSnapClickListener(l);
decoration.setOnRightSnapClickListener(l);
@@ -811,32 +863,47 @@
taskInfo.capturedLinkTimestamp = System.currentTimeMillis();
final String genericLinkString = genericLink == null ? null : genericLink.toString();
doReturn(genericLinkString).when(mMockGenericLinksParser).getGenericLink(any());
- final DesktopModeWindowDecoration decor = createWindowDecoration(taskInfo);
// Relayout to set captured link
- decor.relayout(taskInfo);
- return decor;
+ return createWindowDecoration(taskInfo, new FakeMaximizeMenuFactory(), true /* relayout */);
}
private DesktopModeWindowDecoration createWindowDecoration(
ActivityManager.RunningTaskInfo taskInfo) {
- return createWindowDecoration(taskInfo, new FakeMaximizeMenuFactory());
+ return createWindowDecoration(taskInfo, new FakeMaximizeMenuFactory(),
+ false /* relayout */);
+ }
+
+ private DesktopModeWindowDecoration createWindowDecoration(
+ ActivityManager.RunningTaskInfo taskInfo, boolean relayout) {
+ return createWindowDecoration(taskInfo, new FakeMaximizeMenuFactory(), relayout);
}
private DesktopModeWindowDecoration createWindowDecoration(
ActivityManager.RunningTaskInfo taskInfo,
MaximizeMenuFactory maximizeMenuFactory) {
+ return createWindowDecoration(taskInfo, maximizeMenuFactory, false /* relayout */);
+ }
+
+ private DesktopModeWindowDecoration createWindowDecoration(
+ ActivityManager.RunningTaskInfo taskInfo,
+ MaximizeMenuFactory maximizeMenuFactory,
+ boolean relayout) {
final DesktopModeWindowDecoration windowDecor = new DesktopModeWindowDecoration(mContext,
- mMockDisplayController, mMockSplitScreenController, mMockShellTaskOrganizer,
- taskInfo, mMockSurfaceControl, mMockHandler, mBgExecutor, mMockChoreographer,
- mMockSyncQueue, mMockRootTaskDisplayAreaOrganizer, mMockGenericLinksParser,
- SurfaceControl.Builder::new, mMockTransactionSupplier,
+ mContext, mMockDisplayController, mMockSplitScreenController,
+ mMockShellTaskOrganizer, taskInfo, mMockSurfaceControl, mMockHandler, mBgExecutor,
+ mMockChoreographer, mMockSyncQueue, mMockRootTaskDisplayAreaOrganizer,
+ mMockGenericLinksParser, SurfaceControl.Builder::new, mMockTransactionSupplier,
WindowContainerTransaction::new, SurfaceControl::new,
- mMockSurfaceControlViewHostFactory, maximizeMenuFactory, mMockHandleMenuFactory);
+ mMockSurfaceControlViewHostFactory, maximizeMenuFactory, mMockHandleMenuFactory,
+ mMockMultiInstanceHelper);
windowDecor.setCaptionListeners(mMockTouchEventListener, mMockTouchEventListener,
mMockTouchEventListener, mMockTouchEventListener);
windowDecor.setExclusionRegionListener(mMockExclusionRegionListener);
windowDecor.setOpenInBrowserClickListener(mMockOpenInBrowserClickListener);
windowDecor.mDecorWindowContext = mContext;
+ if (relayout) {
+ windowDecor.relayout(taskInfo);
+ }
return windowDecor;
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java
index 6a94cd8..77337a0 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java
@@ -25,6 +25,7 @@
import static com.google.common.truth.Truth.assertThat;
import android.annotation.NonNull;
+import android.content.Context;
import android.graphics.Point;
import android.graphics.Region;
import android.platform.test.annotations.DisableFlags;
@@ -36,6 +37,7 @@
import androidx.test.filters.SmallTest;
import com.android.window.flags.Flags;
+import com.android.wm.shell.ShellTestCase;
import com.google.common.testing.EqualsTester;
@@ -51,7 +53,7 @@
*/
@SmallTest
@RunWith(AndroidTestingRunner.class)
-public class DragResizeWindowGeometryTests {
+public class DragResizeWindowGeometryTests extends ShellTestCase {
private static final Size TASK_SIZE = new Size(500, 1000);
private static final int TASK_CORNER_RADIUS = 10;
private static final int EDGE_RESIZE_THICKNESS = 15;
@@ -107,7 +109,7 @@
@Test
public void testRegionUnionContainsEdges() {
Region region = new Region();
- GEOMETRY.union(region);
+ GEOMETRY.union(mContext, region);
assertThat(region.isComplex()).isTrue();
// Region excludes task area. Note that coordinates start from top left.
assertThat(region.contains(TASK_SIZE.getWidth() / 2, TASK_SIZE.getHeight() / 2)).isFalse();
@@ -147,10 +149,10 @@
@EnableFlags(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE)
public void testRegionUnion_edgeDragResizeEnabled_containsLargeCorners() {
Region region = new Region();
- GEOMETRY.union(region);
+ GEOMETRY.union(mContext, region);
final int cornerRadius = LARGE_CORNER_SIZE / 2;
- new TestPoints(TASK_SIZE, cornerRadius).validateRegion(region);
+ new TestPoints(mContext, TASK_SIZE, cornerRadius).validateRegion(region);
}
/**
@@ -161,10 +163,10 @@
@DisableFlags(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE)
public void testRegionUnion_edgeDragResizeDisabled_containsFineCorners() {
Region region = new Region();
- GEOMETRY.union(region);
+ GEOMETRY.union(mContext, region);
final int cornerRadius = FINE_CORNER_SIZE / 2;
- new TestPoints(TASK_SIZE, cornerRadius).validateRegion(region);
+ new TestPoints(mContext, TASK_SIZE, cornerRadius).validateRegion(region);
}
@Test
@@ -186,16 +188,16 @@
}
private void validateCtrlTypeForEdges(boolean isTouchscreen, boolean isEdgeResizePermitted) {
- assertThat(GEOMETRY.calculateCtrlType(isTouchscreen, isEdgeResizePermitted,
+ assertThat(GEOMETRY.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted,
LEFT_EDGE_POINT.x, LEFT_EDGE_POINT.y)).isEqualTo(
isEdgeResizePermitted ? CTRL_TYPE_LEFT : CTRL_TYPE_UNDEFINED);
- assertThat(GEOMETRY.calculateCtrlType(isTouchscreen, isEdgeResizePermitted,
+ assertThat(GEOMETRY.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted,
TOP_EDGE_POINT.x, TOP_EDGE_POINT.y)).isEqualTo(
isEdgeResizePermitted ? CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED);
- assertThat(GEOMETRY.calculateCtrlType(isTouchscreen, isEdgeResizePermitted,
+ assertThat(GEOMETRY.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted,
RIGHT_EDGE_POINT.x, RIGHT_EDGE_POINT.y)).isEqualTo(
isEdgeResizePermitted ? CTRL_TYPE_RIGHT : CTRL_TYPE_UNDEFINED);
- assertThat(GEOMETRY.calculateCtrlType(isTouchscreen, isEdgeResizePermitted,
+ assertThat(GEOMETRY.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted,
BOTTOM_EDGE_POINT.x, BOTTOM_EDGE_POINT.y)).isEqualTo(
isEdgeResizePermitted ? CTRL_TYPE_BOTTOM : CTRL_TYPE_UNDEFINED);
}
@@ -203,8 +205,9 @@
@Test
@EnableFlags(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE)
public void testCalculateControlType_edgeDragResizeEnabled_corners() {
- final TestPoints fineTestPoints = new TestPoints(TASK_SIZE, FINE_CORNER_SIZE / 2);
- final TestPoints largeCornerTestPoints = new TestPoints(TASK_SIZE, LARGE_CORNER_SIZE / 2);
+ final TestPoints fineTestPoints = new TestPoints(mContext, TASK_SIZE, FINE_CORNER_SIZE / 2);
+ final TestPoints largeCornerTestPoints =
+ new TestPoints(mContext, TASK_SIZE, LARGE_CORNER_SIZE / 2);
// When the flag is enabled, points within fine corners should pass regardless of touch or
// not. Points outside fine corners should not pass when using a course input (non-touch).
@@ -241,8 +244,10 @@
@Test
@DisableFlags(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE)
public void testCalculateControlType_edgeDragResizeDisabled_corners() {
- final TestPoints fineTestPoints = new TestPoints(TASK_SIZE, FINE_CORNER_SIZE / 2);
- final TestPoints largeCornerTestPoints = new TestPoints(TASK_SIZE, LARGE_CORNER_SIZE / 2);
+ final TestPoints fineTestPoints =
+ new TestPoints(mContext, TASK_SIZE, FINE_CORNER_SIZE / 2);
+ final TestPoints largeCornerTestPoints =
+ new TestPoints(mContext, TASK_SIZE, LARGE_CORNER_SIZE / 2);
// When the flag is disabled, points within fine corners should pass only from touchscreen.
// Edge resize permitted (indicating the event is from a cursor/stylus) should have no
@@ -284,6 +289,7 @@
* <p>Creates points that are both just within the bounds of each corner, and just outside.
*/
private static final class TestPoints {
+ private final Context mContext;
private final Point mTopLeftPoint;
private final Point mTopLeftPointOutside;
private final Point mTopRightPoint;
@@ -293,7 +299,8 @@
private final Point mBottomRightPoint;
private final Point mBottomRightPointOutside;
- TestPoints(@NonNull Size taskSize, int cornerRadius) {
+ TestPoints(@NonNull Context context, @NonNull Size taskSize, int cornerRadius) {
+ mContext = context;
// Point just inside corner square is included.
mTopLeftPoint = new Point(-cornerRadius + 1, -cornerRadius + 1);
// Point just outside corner square is excluded.
@@ -340,17 +347,17 @@
public void validateCtrlTypeForInnerPoints(@NonNull DragResizeWindowGeometry geometry,
boolean isTouchscreen, boolean isEdgeResizePermitted,
boolean expectedWithinGeometry) {
- assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted,
+ assertThat(geometry.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted,
mTopLeftPoint.x, mTopLeftPoint.y)).isEqualTo(
expectedWithinGeometry ? CTRL_TYPE_LEFT | CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED);
- assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted,
+ assertThat(geometry.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted,
mTopRightPoint.x, mTopRightPoint.y)).isEqualTo(
expectedWithinGeometry ? CTRL_TYPE_RIGHT | CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED);
- assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted,
+ assertThat(geometry.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted,
mBottomLeftPoint.x, mBottomLeftPoint.y)).isEqualTo(
expectedWithinGeometry ? CTRL_TYPE_LEFT | CTRL_TYPE_BOTTOM
: CTRL_TYPE_UNDEFINED);
- assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted,
+ assertThat(geometry.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted,
mBottomRightPoint.x, mBottomRightPoint.y)).isEqualTo(
expectedWithinGeometry ? CTRL_TYPE_RIGHT | CTRL_TYPE_BOTTOM
: CTRL_TYPE_UNDEFINED);
@@ -363,17 +370,17 @@
public void validateCtrlTypeForOutsidePoints(@NonNull DragResizeWindowGeometry geometry,
boolean isTouchscreen, boolean isEdgeResizePermitted,
boolean expectedWithinGeometry) {
- assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted,
+ assertThat(geometry.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted,
mTopLeftPointOutside.x, mTopLeftPointOutside.y)).isEqualTo(
expectedWithinGeometry ? CTRL_TYPE_LEFT | CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED);
- assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted,
+ assertThat(geometry.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted,
mTopRightPointOutside.x, mTopRightPointOutside.y)).isEqualTo(
expectedWithinGeometry ? CTRL_TYPE_RIGHT | CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED);
- assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted,
+ assertThat(geometry.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted,
mBottomLeftPointOutside.x, mBottomLeftPointOutside.y)).isEqualTo(
expectedWithinGeometry ? CTRL_TYPE_LEFT | CTRL_TYPE_BOTTOM
: CTRL_TYPE_UNDEFINED);
- assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted,
+ assertThat(geometry.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted,
mBottomRightPointOutside.x, mBottomRightPointOutside.y)).isEqualTo(
expectedWithinGeometry ? CTRL_TYPE_RIGHT | CTRL_TYPE_BOTTOM
: CTRL_TYPE_UNDEFINED);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
index 6667504..2ce59ff 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
@@ -35,7 +35,6 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.any
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt
index ed43aa3..a1c7947 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt
@@ -57,6 +57,7 @@
import org.mockito.Mock
import org.mockito.Mockito.mock
import org.mockito.kotlin.any
+import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
/**
@@ -109,6 +110,9 @@
whenever(mockDesktopWindowDecoration.addWindow(
anyInt(), any(), any(), any(), anyInt(), anyInt(), anyInt(), anyInt())
).thenReturn(mockAdditionalViewHostViewContainer)
+ whenever(mockDesktopWindowDecoration.addWindow(
+ any<View>(), any(), any(), any(), anyInt(), anyInt(), anyInt(), anyInt())
+ ).thenReturn(mockAdditionalViewHostViewContainer)
whenever(mockAdditionalViewHostViewContainer.view).thenReturn(menuView)
whenever(displayController.getDisplayLayout(anyInt())).thenReturn(displayLayout)
whenever(displayLayout.width()).thenReturn(DISPLAY_BOUNDS.width())
@@ -226,13 +230,13 @@
}
else -> error("Invalid windowing mode")
}
- val handleMenu = HandleMenu(mockDesktopWindowDecoration, layoutId,
- onClickListener, onTouchListener, appIcon, appName, displayController,
- splitScreenController, shouldShowWindowingPill = true,
- null /* openInBrowserLink */, captionWidth = HANDLE_WIDTH, captionHeight = 50,
- captionX = captionX
+ val handleMenu = HandleMenu(mockDesktopWindowDecoration, layoutId, appIcon, appName,
+ splitScreenController, shouldShowWindowingPill = true,
+ shouldShowNewWindowButton = true,
+ null /* openInBrowserLink */, captionWidth = HANDLE_WIDTH, captionHeight = 50,
+ captionX = captionX
)
- handleMenu.show()
+ handleMenu.show(mock(), mock(), mock(), mock(), mock(), mock(), mock())
return handleMenu
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
index 943c313..08a6e1b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
@@ -200,7 +200,7 @@
verify(mockTransaction).setPosition(any(), eq(rectAfterMove.left.toFloat()),
eq(rectAfterMove.top.toFloat()))
- taskPositioner.onDragPositioningEnd(
+ val endBounds = taskPositioner.onDragPositioningEnd(
STARTING_BOUNDS.left.toFloat() + 70,
STARTING_BOUNDS.top.toFloat() + 20
)
@@ -212,12 +212,7 @@
verify(mockDesktopWindowDecoration, never()).showResizeVeil(any())
verify(mockDesktopWindowDecoration, never()).hideResizeVeil()
- verify(mockTransitions).startTransition(eq(TRANSIT_CHANGE), argThat { wct ->
- return@argThat wct.changes.any { (token, change) ->
- token == taskBinder &&
- (change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0 &&
- change.configuration.windowConfiguration.bounds == rectAfterEnd }},
- eq(taskPositioner))
+ Assert.assertEquals(rectAfterEnd, endBounds)
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index ca6e03c..2ec3ab5 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -51,6 +51,7 @@
import static org.mockito.Mockito.when;
import static org.mockito.quality.Strictness.LENIENT;
+import android.annotation.NonNull;
import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Resources;
@@ -866,6 +867,7 @@
final TestWindowDecoration windowDecor = createWindowDecoration(
new TestRunningTaskInfoBuilder().build());
mRelayoutParams.mApplyStartTransactionOnDraw = true;
+ mRelayoutResult.mRootView = mMockView;
windowDecor.updateViewHost(mRelayoutParams, mMockSurfaceControlStartT, mRelayoutResult);
@@ -877,6 +879,7 @@
final TestWindowDecoration windowDecor = createWindowDecoration(
new TestRunningTaskInfoBuilder().build());
mRelayoutParams.mApplyStartTransactionOnDraw = true;
+ mRelayoutResult.mRootView = mMockView;
assertThrows(IllegalArgumentException.class,
() -> windowDecor.updateViewHost(
@@ -888,13 +891,14 @@
final TestWindowDecoration windowDecor = createWindowDecoration(
new TestRunningTaskInfoBuilder().build());
mRelayoutParams.mApplyStartTransactionOnDraw = false;
+ mRelayoutResult.mRootView = mMockView;
windowDecor.updateViewHost(mRelayoutParams, null /* onDrawTransaction */, mRelayoutResult);
}
private TestWindowDecoration createWindowDecoration(ActivityManager.RunningTaskInfo taskInfo) {
- return new TestWindowDecoration(mContext, mMockDisplayController, mMockShellTaskOrganizer,
- taskInfo, mMockTaskSurface,
+ return new TestWindowDecoration(mContext, mContext, mMockDisplayController,
+ mMockShellTaskOrganizer, taskInfo, mMockTaskSurface,
new MockObjectSupplier<>(mMockSurfaceControlBuilders,
() -> createMockSurfaceControlBuilder(mock(SurfaceControl.class))),
new MockObjectSupplier<>(mMockSurfaceControlTransactions,
@@ -932,7 +936,8 @@
}
private class TestWindowDecoration extends WindowDecoration<TestView> {
- TestWindowDecoration(Context context, DisplayController displayController,
+ TestWindowDecoration(Context context, @NonNull Context userContext,
+ DisplayController displayController,
ShellTaskOrganizer taskOrganizer, ActivityManager.RunningTaskInfo taskInfo,
SurfaceControl taskSurface,
Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
@@ -940,7 +945,7 @@
Supplier<WindowContainerTransaction> windowContainerTransactionSupplier,
Supplier<SurfaceControl> surfaceControlSupplier,
SurfaceControlViewHostFactory surfaceControlViewHostFactory) {
- super(context, displayController, taskOrganizer, taskInfo, taskSurface,
+ super(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface,
surfaceControlBuilderSupplier, surfaceControlTransactionSupplier,
windowContainerTransactionSupplier, surfaceControlSupplier,
surfaceControlViewHostFactory);
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index 0d5af50..8b6194f 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -27,6 +27,7 @@
import android.telephony.emergency.EmergencyNumber;
import android.util.Log;
+import com.android.internal.annotations.KeepForWeakReference;
import com.android.internal.telephony.flags.Flags;
import java.util.concurrent.TimeUnit;
@@ -94,6 +95,7 @@
// The internal implementation of TelephonyManager uses WeakReference so we have to keep a
// reference here.
+ @KeepForWeakReference
private final EmergencyCallListener mEmergencyCallListener = new EmergencyCallListener();
private final EmergencyCallCallback mEmergencyCallCallback;
diff --git a/media/java/android/media/tv/flags/media_tv.aconfig b/media/java/android/media/tv/flags/media_tv.aconfig
index 97971e1..3196ba1 100644
--- a/media/java/android/media/tv/flags/media_tv.aconfig
+++ b/media/java/android/media/tv/flags/media_tv.aconfig
@@ -23,4 +23,12 @@
namespace: "media_tv"
description: "TIAF V3.0 APIs for Android V"
bug: "303323657"
+}
+
+flag {
+ name: "tis_always_bound_permission"
+ is_exported: true
+ namespace: "media_tv"
+ description: "Introduce ALWAYS_BOUND_TV_INPUT for TIS."
+ bug: "332201346"
}
\ No newline at end of file
diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp
index 8f16f76..0fb3049 100644
--- a/native/graphics/jni/Android.bp
+++ b/native/graphics/jni/Android.bp
@@ -127,3 +127,30 @@
"-DPNG_MUTATOR_DEFINE_LIBFUZZER_CUSTOM_MUTATOR",
],
}
+
+cc_fuzz {
+ name: "imagedecoder_heif_fuzzer",
+ defaults: ["imagedecoder_fuzzer_defaults"],
+ team: "trendy_team_android_core_graphics_stack",
+ shared_libs: [
+ "libfakeservicemanager",
+ ],
+ target: {
+ android: {
+ shared_libs: [
+ "libmediaplayerservice",
+ "libmediaextractorservice",
+ ],
+ },
+ host: {
+ static_libs: [
+ "libbinder_random_parcel",
+ "libcutils",
+ ],
+ },
+ },
+ include_dirs: ["frameworks/av/services/mediaextractor"],
+ cflags: [
+ "-DFUZZ_HEIF_FORMAT",
+ ],
+}
diff --git a/native/graphics/jni/fuzz/fuzz_imagedecoder.cpp b/native/graphics/jni/fuzz/fuzz_imagedecoder.cpp
index 6743997..f739e4a 100644
--- a/native/graphics/jni/fuzz/fuzz_imagedecoder.cpp
+++ b/native/graphics/jni/fuzz/fuzz_imagedecoder.cpp
@@ -18,6 +18,16 @@
#include <binder/IPCThreadState.h>
#include <fuzzer/FuzzedDataProvider.h>
+#ifdef FUZZ_HEIF_FORMAT
+#include <fakeservicemanager/FakeServiceManager.h>
+#ifdef __ANDROID__
+#include <MediaExtractorService.h>
+#include <MediaPlayerService.h>
+#else
+#include <fuzzbinder/random_binder.h>
+#endif //__ANDROID__
+#endif // FUZZ_HEIF_FORMAT
+
#ifdef PNG_MUTATOR_DEFINE_LIBFUZZER_CUSTOM_MUTATOR
#include <fuzz/png_mutator.h>
#endif
@@ -31,8 +41,42 @@
using PixelPointer = std::unique_ptr<void, PixelFreer>;
+#ifndef FUZZ_HEIF_FORMAT
+#define FOURCC(c1, c2, c3, c4) ((c1) << 24 | (c2) << 16 | (c3) << 8 | (c4))
+/** Reverse all 4 bytes in a 32bit value.
+ e.g. 0x12345678 -> 0x78563412
+*/
+static uint32_t endianSwap32(uint32_t value) {
+ return ((value & 0xFF) << 24) | ((value & 0xFF00) << 8) | ((value & 0xFF0000) >> 8) |
+ (value >> 24);
+}
+
+static bool isFtyp(const uint8_t* data, size_t size) {
+ constexpr int32_t headerSize = 8;
+ constexpr int32_t chunkTypeOffset = 4;
+ constexpr int32_t ftypFourCCVal = FOURCC('f', 't', 'y', 'p');
+ if (size >= headerSize) {
+ const uint32_t* chunk = reinterpret_cast<const uint32_t*>(data + chunkTypeOffset);
+ if (endianSwap32(*chunk) == ftypFourCCVal) {
+ return true;
+ }
+ }
+ return false;
+}
+#endif
+
AImageDecoder* init(const uint8_t* data, size_t size, bool useFileDescriptor) {
AImageDecoder* decoder = nullptr;
+#ifndef FUZZ_HEIF_FORMAT
+ if (isFtyp(data, size)) {
+ /* We want to ignore HEIF data when fuzzing non-HEIF image decoders. Use 'FTYP'
+ * as a signal to ignore, though note that this excludes more than just HEIF.
+ * But when this code was added, `AImageDecoder` did not support any formats
+ * in 'FTYP' besides HEIF.
+ */
+ return nullptr;
+ }
+#endif // FUZZ_HEIF_FORMAT
if (useFileDescriptor) {
constexpr char testFd[] = "tempFd";
int32_t fileDesc = open(testFd, O_RDWR | O_CREAT | O_TRUNC);
@@ -47,6 +91,27 @@
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
FuzzedDataProvider dataProvider = FuzzedDataProvider(data, size);
+#ifdef FUZZ_HEIF_FORMAT
+ /**
+ * For image formats like HEIF, a new metadata object is
+ * created which requires "media.player" service running
+ */
+ static std::once_flag callOnceHEIF;
+ std::call_once(callOnceHEIF, [&]() {
+ android::sp<android::IServiceManager> fakeServiceManager =
+ new android::FakeServiceManager();
+ setDefaultServiceManager(fakeServiceManager);
+#ifdef __ANDROID__
+ android::MediaPlayerService::instantiate();
+ android::MediaExtractorService::instantiate();
+#else
+ auto binderExtractor = android::getRandomBinder(&dataProvider);
+ auto binderPlayer = android::getRandomBinder(&dataProvider);
+ fakeServiceManager->addService(android::String16("media.extractor"), binderExtractor);
+ fakeServiceManager->addService(android::String16("media.player"), binderPlayer);
+#endif //__ANDROID__
+ });
+#endif // FUZZ_HEIF_FORMAT
/**
* Use maximum of 80% of buffer for creating decoder and save at least
* 20% buffer for fuzzing other APIs
diff --git a/packages/CompanionDeviceManager/res/values/strings.xml b/packages/CompanionDeviceManager/res/values/strings.xml
index 42d0cc4..a57d6eb 100644
--- a/packages/CompanionDeviceManager/res/values/strings.xml
+++ b/packages/CompanionDeviceManager/res/values/strings.xml
@@ -34,7 +34,7 @@
<string name="chooser_title">Choose a <xliff:g id="profile_name" example="watch">%1$s</xliff:g> to set up</string>
<!-- Description of the privileges the application will get if associated with the companion device of WATCH profile [CHAR LIMIT=NONE] -->
- <string name="summary_watch">This app will be allowed to sync info, like the name of someone calling, and access these permissions on your <xliff:g id="device_name" example="phone">%1$s</xliff:g></string>
+ <string name="summary_watch">This app will be allowed to sync info, like the name of someone calling, and access these permissions on your <xliff:g id="device_type" example="phone">%1$s</xliff:g></string>
<!-- ================= DEVICE_PROFILE_GLASSES ================= -->
@@ -45,27 +45,18 @@
<string name="profile_name_glasses">device</string>
<!-- Description of the privileges the application will get if associated with the companion device of GLASSES profile [CHAR LIMIT=NONE] -->
- <string name="summary_glasses">This app will be allowed to access these permissions on your <xliff:g id="device_name" example="phone">%1$s</xliff:g></string>
+ <string name="summary_glasses">This app will be allowed to access these permissions on your <xliff:g id="device_type" example="phone">%1$s</xliff:g></string>
<!-- ================= DEVICE_PROFILE_APP_STREAMING ================= -->
<!-- Confirmation for associating an application with a companion device of APP_STREAMING profile (type) [CHAR LIMIT=NONE] -->
- <string name="title_app_streaming">Allow <strong><xliff:g id="app_name" example="Exo">%1$s</xliff:g></strong> to access this information from your phone</string>
-
- <!-- Confirmation for associating an application with a companion device of APP_STREAMING profile (type) with mirroring enabled [CHAR LIMIT=NONE] -->
- <string name="title_app_streaming_with_mirroring">Allow <strong><xliff:g id="app_name" example="Exo">%1$s</xliff:g></strong> to stream your phone\u2019s apps?</string>
+ <string name="title_app_streaming">Allow <strong><xliff:g id="app_name" example="Exo">%1$s</xliff:g></strong> to stream your <xliff:g id="device_type" example="phone">%2$s</xliff:g>\u2019s apps to <strong><xliff:g id="device_name" example="Chromebook">%3$s</xliff:g></strong>?</string>
<!-- Summary for associating an application with a companion device of APP_STREAMING profile [CHAR LIMIT=NONE] -->
- <string name="summary_app_streaming">%1$s will have access to anything that’s visible or played on the phone, including audio, photos, passwords, and messages.<br/><br/>%1$s will be able to stream apps until you remove access to this permission.</string>
-
- <!-- Title of the helper dialog for APP_STREAMING profile [CHAR LIMIT=30]. -->
- <string name="helper_title_app_streaming">Cross-device services</string>
+ <string name="summary_app_streaming"><xliff:g id="app_name" example="Exo">%1$s</xliff:g> will have access to anything that’s visible or played on the <xliff:g id="device_type" example="phone">%2$s</xliff:g>, including audio, photos, passwords, and messages.<br/><br/><xliff:g id="app_name" example="Exo">%1$s</xliff:g> will be able to stream apps to <xliff:g id="device_name" example="Chromebook">%3$s</xliff:g> until you remove access to this permission.</string>
<!-- Description of the helper dialog for APP_STREAMING profile. [CHAR LIMIT=NONE] -->
- <string name="helper_summary_app_streaming"><xliff:g id="app_name" example="GMS">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="display_name" example="Chromebook">%2$s</xliff:g> to stream apps between your devices</string>
-
- <!-- Description of the helper dialog for APP_STREAMING profile with mirroring enabled. [CHAR LIMIT=NONE] -->
- <string name="helper_summary_app_streaming_with_mirroring"><xliff:g id="app_name" example="GMS">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="display_name" example="Chromebook">%2$s</xliff:g> to display and stream apps between your devices</string>
+ <string name="helper_summary_app_streaming"><xliff:g id="app_name" example="GMS">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="device_name" example="Chromebook">%2$s</xliff:g> to display and stream apps between your devices</string>
<!-- ================= DEVICE_PROFILE_AUTOMOTIVE_PROJECTION ================= -->
@@ -78,30 +69,24 @@
<!-- ================= DEVICE_PROFILE_COMPUTER ================= -->
<!-- Confirmation for associating an application with a companion device of COMPUTER profile (type) [CHAR LIMIT=NONE] -->
- <string name="title_computer">Allow <strong><xliff:g id="app_name" example="GMS">%1$s</xliff:g></strong> to access this information from your phone</string>
+ <string name="title_computer">Allow <strong><xliff:g id="app_name" example="GMS">%1$s</xliff:g></strong> to access this information from your <xliff:g id="device_type" example="phone">%2$s</xliff:g></string>
<!-- Description of the privileges the application will get if associated with the companion device of COMPUTER profile (type) [CHAR LIMIT=NONE] -->
<string name="summary_computer"></string>
- <!-- Title of the helper dialog for COMPUTER profile [CHAR LIMIT=30]. -->
- <string name="helper_title_computer">Google Play services</string>
-
<!-- Description of the helper dialog for COMPUTER profile. [CHAR LIMIT=NONE] -->
- <string name="helper_summary_computer"><xliff:g id="app_name" example="GMS">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="display_name" example="Chromebook">%2$s</xliff:g> to access your phone\u2019s photos, media, and notifications</string>
+ <string name="helper_summary_computer"><xliff:g id="app_name" example="GMS">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="device_name" example="Chromebook">%2$s</xliff:g> to access your <xliff:g id="device_type" example="phone">%3$s</xliff:g>\u2019s photos, media, and notifications</string>
<!-- ================= DEVICE_PROFILE_NEARBY_DEVICE_STREAMING ================= -->
<!-- Confirmation for associating an application with a companion device of NEARBY_DEVICE_STREAMING profile (type) [CHAR LIMIT=NONE] -->
- <string name="title_nearby_device_streaming">Allow <strong><xliff:g id="device_name" example="NearbyStreamer">%1$s</xliff:g></strong> to take this action?</string>
-
- <!-- Confirmation for associating an application with a companion device of NEARBY_DEVICE_STREAMING profile (type) with mirroring enabled [CHAR LIMIT=NONE] -->
- <string name="title_nearby_device_streaming_with_mirroring">Allow <strong><xliff:g id="device_name" example="NearbyStreamer">%1$s</xliff:g></strong> to stream your phone\u2019s apps and system features?</string>
+ <string name="title_nearby_device_streaming">Allow <strong><xliff:g id="device_name" example="NearbyStreamer">%1$s</xliff:g></strong> to stream your <xliff:g id="device_type" example="phone">%2$s</xliff:g>\u2019s apps and system features to <strong><xliff:g id="device_name" example="Chromebook">%3$s</xliff:g></strong>?</string>
<!-- Summary for associating an application with a companion device of NEARBY_DEVICE_STREAMING profile [CHAR LIMIT=NONE] -->
- <string name="summary_nearby_device_streaming">%1$s will have access to anything that’s visible or played on your phone, including audio, photos, payment info, passwords, and messages.<br/><br/>%1$s will be able to stream apps and system features until you remove access to this permission.</string>
+ <string name="summary_nearby_device_streaming"><xliff:g id="app_name" example="Exo">%1$s</xliff:g> will have access to anything that’s visible or played on your <xliff:g id="device_type" example="phone">%2$s</xliff:g>, including audio, photos, payment info, passwords, and messages.<br/><br/><xliff:g id="app_name" example="Exo">%1$s</xliff:g> will be able to stream apps and system features to <xliff:g id="device_name" example="Chromebook">%3$s</xliff:g> until you remove access to this permission.</string>
<!-- Description of the helper dialog for NEARBY_DEVICE_STREAMING profile. [CHAR LIMIT=NONE] -->
- <string name="helper_summary_nearby_device_streaming"><xliff:g id="app_name" example="NearbyStreamerApp">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="device_name" example="NearbyDevice">%2$s</xliff:g> to stream apps and other system features to nearby devices</string>
+ <string name="helper_summary_nearby_device_streaming"><xliff:g id="app_name" example="NearbyStreamerApp">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="device_name" example="NearbyDevice">%2$s</xliff:g> to stream apps and other system features between your devices</string>
<!-- ================= null profile ================= -->
@@ -173,12 +158,6 @@
<!-- Notification permission will be granted of corresponding profile [CHAR LIMIT=30] -->
<string name="permission_notifications">Notifications</string>
- <!-- Apps permission will be granted of corresponding profile [CHAR LIMIT=30] -->
- <string name="permission_app_streaming">Apps</string>
-
- <!-- Nearby_device_streaming permission will be granted to the corresponding profile [CHAR LIMIT=45] -->
- <string name="permission_nearby_device_streaming">Streaming</string>
-
<!-- Description of phone permission of corresponding profile [CHAR LIMIT=NONE] -->
<string name="permission_phone_summary">Make and manage phone calls</string>
@@ -206,15 +185,9 @@
<!-- Description of NLA & POST_NOTIFICATION of corresponding profile [CHAR LIMIT=NONE] -->
<string name="permission_notifications_summary">\u2022 Read all notifications, including info like contacts, messages, and photos<br/>\u2022 Send notifications<br/><br/>You can manage this app\'s ability to read and send notifications anytime in Settings > Notifications.</string>
- <!-- Description of app streaming permission of corresponding profile [CHAR LIMIT=NONE] -->
- <string name="permission_app_streaming_summary">Stream your phone\u2019s apps</string>
-
<!-- Description of storage permission of corresponding profile [CHAR LIMIT=NONE] -->
<string name="permission_storage_summary"></string>
- <!-- Description of nearby_device_streaming permission of corresponding profile [CHAR LIMIT=NONE] -->
- <string name="permission_nearby_device_streaming_summary">Stream apps and other system features from your phone</string>
-
<!-- Description of change media output permission to be granted to the corresponding profile [CHAR LIMIT=NONE] -->
<string name="permission_media_routing_control_summary">Access a list of available devices and control which one streams or casts audio or video from other apps</string>
@@ -224,4 +197,10 @@
<!-- The type of the device for tablet [CHAR LIMIT=30] -->
<string name="device_type" product="tablet">tablet</string>
+ <!-- The type of the device for TV [CHAR LIMIT=30] -->
+ <string name="device_type" product="tv">tv</string>
+
+ <!-- The type of the device for other device [CHAR LIMIT=30] -->
+ <string name="device_type" product="device">device</string>
+
</resources>
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java
index e005334..6117330 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java
@@ -440,12 +440,13 @@
return;
}
- title = getHtmlFromResources(this, PROFILE_TITLES.get(deviceProfile), deviceName);
+ title = getHtmlFromResources(this, PROFILE_TITLES.get(deviceProfile), mAppLabel,
+ getString(R.string.device_type), deviceName);
if (PROFILE_SUMMARIES.containsKey(deviceProfile)) {
final int summaryResourceId = PROFILE_SUMMARIES.get(deviceProfile);
final Spanned summary = getHtmlFromResources(this, summaryResourceId,
- deviceName);
+ mAppLabel, getString(R.string.device_type), deviceName);
mSummary.setText(summary);
} else {
mSummary.setVisibility(View.GONE);
@@ -646,6 +647,11 @@
// and when mPermissionListRecyclerView is fully populated.
// Lastly, disable the Allow and Don't allow buttons.
private void setupPermissionList(String deviceProfile) {
+ if (!PROFILE_PERMISSIONS.containsKey(deviceProfile)) {
+ // Nothing to do if there are no permission types.
+ return;
+ }
+
final List<Integer> permissionTypes = new ArrayList<>(
PROFILE_PERMISSIONS.get(deviceProfile));
if (permissionTypes.isEmpty()) {
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java
index dc68bcc..37b1f29 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java
@@ -27,13 +27,11 @@
import static java.util.Collections.unmodifiableMap;
import static java.util.Collections.unmodifiableSet;
-import android.companion.virtual.flags.Flags;
import android.os.Build;
import android.util.ArrayMap;
import android.util.ArraySet;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -47,31 +45,27 @@
// Permission resources
private static final int PERMISSION_NOTIFICATION_LISTENER_ACCESS = 0;
private static final int PERMISSION_STORAGE = 1;
- private static final int PERMISSION_APP_STREAMING = 2;
- private static final int PERMISSION_PHONE = 3;
- private static final int PERMISSION_SMS = 4;
- private static final int PERMISSION_CONTACTS = 5;
- private static final int PERMISSION_CALENDAR = 6;
- private static final int PERMISSION_NEARBY_DEVICES = 7;
- private static final int PERMISSION_NEARBY_DEVICE_STREAMING = 8;
- private static final int PERMISSION_MICROPHONE = 9;
- private static final int PERMISSION_CALL_LOGS = 10;
+ private static final int PERMISSION_PHONE = 2;
+ private static final int PERMISSION_SMS = 3;
+ private static final int PERMISSION_CONTACTS = 4;
+ private static final int PERMISSION_CALENDAR = 5;
+ private static final int PERMISSION_NEARBY_DEVICES = 6;
+ private static final int PERMISSION_MICROPHONE = 7;
+ private static final int PERMISSION_CALL_LOGS = 8;
// Notification Listener Access & POST_NOTIFICATION permission
- private static final int PERMISSION_NOTIFICATIONS = 11;
- private static final int PERMISSION_CHANGE_MEDIA_OUTPUT = 12;
+ private static final int PERMISSION_NOTIFICATIONS = 9;
+ private static final int PERMISSION_CHANGE_MEDIA_OUTPUT = 10;
static final Map<Integer, Integer> PERMISSION_TITLES;
static {
final Map<Integer, Integer> map = new ArrayMap<>();
map.put(PERMISSION_NOTIFICATION_LISTENER_ACCESS, R.string.permission_notifications);
map.put(PERMISSION_STORAGE, R.string.permission_storage);
- map.put(PERMISSION_APP_STREAMING, R.string.permission_app_streaming);
map.put(PERMISSION_PHONE, R.string.permission_phone);
map.put(PERMISSION_SMS, R.string.permission_sms);
map.put(PERMISSION_CONTACTS, R.string.permission_contacts);
map.put(PERMISSION_CALENDAR, R.string.permission_calendar);
map.put(PERMISSION_NEARBY_DEVICES, R.string.permission_nearby_devices);
- map.put(PERMISSION_NEARBY_DEVICE_STREAMING, R.string.permission_nearby_device_streaming);
map.put(PERMISSION_MICROPHONE, R.string.permission_microphone);
map.put(PERMISSION_CALL_LOGS, R.string.permission_call_logs);
map.put(PERMISSION_NOTIFICATIONS, R.string.permission_notifications);
@@ -85,14 +79,11 @@
map.put(PERMISSION_NOTIFICATION_LISTENER_ACCESS,
R.string.permission_notification_listener_access_summary);
map.put(PERMISSION_STORAGE, R.string.permission_storage_summary);
- map.put(PERMISSION_APP_STREAMING, R.string.permission_app_streaming_summary);
map.put(PERMISSION_PHONE, R.string.permission_phone_summary);
map.put(PERMISSION_SMS, R.string.permission_sms_summary);
map.put(PERMISSION_CONTACTS, R.string.permission_contacts_summary);
map.put(PERMISSION_CALENDAR, R.string.permission_calendar_summary);
map.put(PERMISSION_NEARBY_DEVICES, R.string.permission_nearby_devices_summary);
- map.put(PERMISSION_NEARBY_DEVICE_STREAMING,
- R.string.permission_nearby_device_streaming_summary);
map.put(PERMISSION_MICROPHONE, R.string.permission_microphone_summary);
map.put(PERMISSION_CALL_LOGS, R.string.permission_call_logs_summary);
map.put(PERMISSION_NOTIFICATIONS, R.string.permission_notifications_summary);
@@ -105,14 +96,11 @@
final Map<Integer, Integer> map = new ArrayMap<>();
map.put(PERMISSION_NOTIFICATION_LISTENER_ACCESS, R.drawable.ic_permission_notifications);
map.put(PERMISSION_STORAGE, R.drawable.ic_permission_storage);
- map.put(PERMISSION_APP_STREAMING, R.drawable.ic_permission_app_streaming);
map.put(PERMISSION_PHONE, R.drawable.ic_permission_phone);
map.put(PERMISSION_SMS, R.drawable.ic_permission_sms);
map.put(PERMISSION_CONTACTS, R.drawable.ic_permission_contacts);
map.put(PERMISSION_CALENDAR, R.drawable.ic_permission_calendar);
map.put(PERMISSION_NEARBY_DEVICES, R.drawable.ic_permission_nearby_devices);
- map.put(PERMISSION_NEARBY_DEVICE_STREAMING,
- R.drawable.ic_permission_nearby_device_streaming);
map.put(PERMISSION_MICROPHONE, R.drawable.ic_permission_microphone);
map.put(PERMISSION_CALL_LOGS, R.drawable.ic_permission_call_logs);
map.put(PERMISSION_NOTIFICATIONS, R.drawable.ic_permission_notifications);
@@ -124,19 +112,10 @@
static final Map<String, Integer> PROFILE_TITLES;
static {
final Map<String, Integer> map = new ArrayMap<>();
- if (Flags.interactiveScreenMirror()) {
- map.put(DEVICE_PROFILE_APP_STREAMING, R.string.title_app_streaming_with_mirroring);
- } else {
- map.put(DEVICE_PROFILE_APP_STREAMING, R.string.title_app_streaming);
- }
+ map.put(DEVICE_PROFILE_APP_STREAMING, R.string.title_app_streaming);
map.put(DEVICE_PROFILE_AUTOMOTIVE_PROJECTION, R.string.title_automotive_projection);
map.put(DEVICE_PROFILE_COMPUTER, R.string.title_computer);
- if (Flags.interactiveScreenMirror()) {
- map.put(DEVICE_PROFILE_NEARBY_DEVICE_STREAMING,
- R.string.title_nearby_device_streaming_with_mirroring);
- } else {
- map.put(DEVICE_PROFILE_NEARBY_DEVICE_STREAMING, R.string.title_nearby_device_streaming);
- }
+ map.put(DEVICE_PROFILE_NEARBY_DEVICE_STREAMING, R.string.title_nearby_device_streaming);
map.put(DEVICE_PROFILE_WATCH, R.string.confirmation_title);
map.put(DEVICE_PROFILE_GLASSES, R.string.confirmation_title_glasses);
map.put(null, R.string.confirmation_title);
@@ -149,29 +128,29 @@
final Map<String, Integer> map = new ArrayMap<>();
map.put(DEVICE_PROFILE_WATCH, R.string.summary_watch);
map.put(DEVICE_PROFILE_GLASSES, R.string.summary_glasses);
- if (Flags.interactiveScreenMirror()) {
- map.put(DEVICE_PROFILE_APP_STREAMING, R.string.summary_app_streaming);
- map.put(DEVICE_PROFILE_NEARBY_DEVICE_STREAMING,
- R.string.summary_nearby_device_streaming);
- }
+ map.put(DEVICE_PROFILE_APP_STREAMING, R.string.summary_app_streaming);
+ map.put(DEVICE_PROFILE_NEARBY_DEVICE_STREAMING, R.string.summary_nearby_device_streaming);
map.put(null, R.string.summary_generic);
PROFILE_SUMMARIES = unmodifiableMap(map);
}
+ static final Map<String, Integer> PROFILE_HELPER_SUMMARIES;
+ static {
+ final Map<String, Integer> map = new ArrayMap<>();
+ map.put(DEVICE_PROFILE_APP_STREAMING, R.string.helper_summary_app_streaming);
+ map.put(DEVICE_PROFILE_NEARBY_DEVICE_STREAMING,
+ R.string.helper_summary_nearby_device_streaming);
+ map.put(DEVICE_PROFILE_COMPUTER, R.string.helper_summary_computer);
+
+ PROFILE_HELPER_SUMMARIES = unmodifiableMap(map);
+ }
+
static final Map<String, List<Integer>> PROFILE_PERMISSIONS;
static {
final Map<String, List<Integer>> map = new ArrayMap<>();
map.put(DEVICE_PROFILE_COMPUTER, Arrays.asList(
PERMISSION_NOTIFICATION_LISTENER_ACCESS, PERMISSION_STORAGE));
- if (Flags.interactiveScreenMirror()) {
- map.put(DEVICE_PROFILE_APP_STREAMING, Collections.emptyList());
- map.put(DEVICE_PROFILE_NEARBY_DEVICE_STREAMING, Collections.emptyList());
- } else {
- map.put(DEVICE_PROFILE_APP_STREAMING, Arrays.asList(PERMISSION_APP_STREAMING));
- map.put(DEVICE_PROFILE_NEARBY_DEVICE_STREAMING,
- Arrays.asList(PERMISSION_NEARBY_DEVICE_STREAMING));
- }
if (Build.VERSION.SDK_INT > UPSIDE_DOWN_CAKE) {
map.put(DEVICE_PROFILE_WATCH, Arrays.asList(PERMISSION_NOTIFICATIONS, PERMISSION_PHONE,
PERMISSION_CALL_LOGS, PERMISSION_SMS, PERMISSION_CONTACTS, PERMISSION_CALENDAR,
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionVendorHelperDialogFragment.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionVendorHelperDialogFragment.java
index fe0e021..ec92987 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionVendorHelperDialogFragment.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionVendorHelperDialogFragment.java
@@ -16,17 +16,13 @@
package com.android.companiondevicemanager;
-import static android.companion.AssociationRequest.DEVICE_PROFILE_APP_STREAMING;
-import static android.companion.AssociationRequest.DEVICE_PROFILE_COMPUTER;
-import static android.companion.AssociationRequest.DEVICE_PROFILE_NEARBY_DEVICE_STREAMING;
-
+import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_HELPER_SUMMARIES;
import static com.android.companiondevicemanager.Utils.getApplicationIcon;
import static com.android.companiondevicemanager.Utils.getApplicationLabel;
import static com.android.companiondevicemanager.Utils.getHtmlFromResources;
import android.annotation.Nullable;
import android.companion.AssociationRequest;
-import android.companion.virtual.flags.Flags;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
@@ -105,7 +101,7 @@
final String deviceProfile = request.getDeviceProfile();
final String packageName = request.getPackageName();
- final CharSequence displayName = request.getDisplayName();
+ final CharSequence deviceName = request.getDisplayName();
final int userId = request.getUserId();
final CharSequence appLabel;
@@ -123,37 +119,17 @@
mAppIcon = view.findViewById(R.id.app_icon);
mButton = view.findViewById(R.id.btn_back);
- final CharSequence title;
- final Spanned summary;
-
- switch (deviceProfile) {
- case DEVICE_PROFILE_APP_STREAMING:
- title = getHtmlFromResources(getContext(), R.string.helper_title_app_streaming);
- summary = getHtmlFromResources(
- getContext(), Flags.interactiveScreenMirror()
- ? R.string.helper_summary_app_streaming_with_mirroring
- : R.string.helper_summary_app_streaming, title, displayName);
- break;
-
- case DEVICE_PROFILE_COMPUTER:
- title = getHtmlFromResources(getContext(), R.string.helper_title_computer);
- summary = getHtmlFromResources(
- getContext(), R.string.helper_summary_computer, title, displayName);
- break;
-
- case DEVICE_PROFILE_NEARBY_DEVICE_STREAMING:
- title = appLabel;
- summary = getHtmlFromResources(
- getContext(), R.string.helper_summary_nearby_device_streaming, title,
- displayName);
- break;
-
- default:
- throw new RuntimeException("Unsupported profile " + deviceProfile);
+ if (PROFILE_HELPER_SUMMARIES.containsKey(deviceProfile)) {
+ final int summaryResourceId = PROFILE_HELPER_SUMMARIES.get(deviceProfile);
+ final Spanned summary = getHtmlFromResources(
+ getContext(), summaryResourceId, appLabel, deviceName,
+ getString(R.string.device_type));
+ mSummary.setText(summary);
+ } else {
+ throw new RuntimeException("Unsupported profile " + deviceProfile);
}
- mTitle.setText(title);
- mSummary.setText(summary);
+ mTitle.setText(appLabel);
mAppIcon.setImageDrawable(applicationIcon);
mButton.setOnClickListener(v -> {
diff --git a/packages/CredentialManager/wear/robotests/src/com/android/credentialmanager/CredentialSelectorUiStateGetMapperTest.kt b/packages/CredentialManager/wear/robotests/src/com/android/credentialmanager/CredentialSelectorUiStateGetMapperTest.kt
index c6013e2..ef4416e 100644
--- a/packages/CredentialManager/wear/robotests/src/com/android/credentialmanager/CredentialSelectorUiStateGetMapperTest.kt
+++ b/packages/CredentialManager/wear/robotests/src/com/android/credentialmanager/CredentialSelectorUiStateGetMapperTest.kt
@@ -30,7 +30,7 @@
import com.google.common.truth.Truth.assertThat
import com.android.credentialmanager.ui.mappers.toGet
import com.android.credentialmanager.model.get.ProviderInfo
-import com.android.credentialmanager.CredentialSelectorUiState.Get.MultipleEntry.PerUserNameEntries
+import com.android.credentialmanager.CredentialSelectorUiState.Get.MultipleEntry.PerNameEntries
/** Unit tests for [CredentialSelectorUiStateGetMapper]. */
@SmallTest
@@ -108,7 +108,7 @@
}
@Test
- fun `On primary screen, multiple accounts returns SingleEntryPerAccount`() {
+ fun `On primary screen, multiple accounts returns MultipleEntryPrimaryScreen`() {
val getCredentialUiState = Request.Get(
token = null,
resultReceiver = null,
@@ -135,7 +135,7 @@
assertThat(getCredentialUiState).isEqualTo(
CredentialSelectorUiState.Get.MultipleEntry(
- listOf(PerUserNameEntries("userName", listOf(
+ listOf(PerNameEntries("userName", listOf(
passkeyCredentialEntryInfo,
passwordCredentialEntryInfo))
),
@@ -155,7 +155,7 @@
assertThat(getCredentialUiState).isEqualTo(
CredentialSelectorUiState.Get.MultipleEntry(
listOf(
- PerUserNameEntries("userName",
+ PerNameEntries("userName",
listOf(
recentlyUsedPasskeyCredential, // from provider 2
passkeyCredentialEntryInfo, // from provider 1 or 2
@@ -164,7 +164,7 @@
passwordCredentialEntryInfo, // from provider 1 or 2
passwordCredentialEntryInfo, // from provider 1 or 2
)),
- PerUserNameEntries("userName2", listOf(unknownCredentialEntryInfo)),
+ PerNameEntries("userName2", listOf(unknownCredentialEntryInfo)),
),
listOf(actionEntryInfo, actionEntryInfo),
listOf(authenticationEntryInfo, authenticationEntryInfo)
@@ -172,8 +172,44 @@
)
}
+ @Test
+ fun `Returned multiple entry is grouped by display name if present`() {
+ val testCred1 = createCredentialEntryInfo(displayName = "testDisplayName",
+ userName = "testUserName", credentialType = CredentialType.PASSWORD)
+ val testCred2 = createCredentialEntryInfo(displayName = "testDisplayName",
+ userName = "testUserName", credentialType = CredentialType.PASSKEY)
+ val getCredentialUiState = Request.Get(
+ token = null,
+ resultReceiver = null,
+ providerInfos = listOf(createProviderInfo(credentialList1),
+ createProviderInfo(credentialList2),
+ createProviderInfo(listOf(testCred1, testCred2))))
+ .toGet(isPrimary = false)
+
+ assertThat(getCredentialUiState).isEqualTo(
+ CredentialSelectorUiState.Get.MultipleEntry(
+ listOf(
+ PerNameEntries("userName",
+ listOf(
+ recentlyUsedPasskeyCredential, // from provider 2
+ passkeyCredentialEntryInfo, // from provider 1 or 2
+ passkeyCredentialEntryInfo, // from provider 1 or 2
+ recentlyUsedPasswordCredential, // from provider 2
+ passwordCredentialEntryInfo, // from provider 1 or 2
+ passwordCredentialEntryInfo, // from provider 1 or 2
+ )),
+ PerNameEntries("userName2", listOf(unknownCredentialEntryInfo)),
+ PerNameEntries("testDisplayName", listOf(testCred2, testCred1)),
+ ),
+ listOf(actionEntryInfo, actionEntryInfo, actionEntryInfo),
+ listOf(authenticationEntryInfo, authenticationEntryInfo, authenticationEntryInfo)
+ )
+ )
+ }
+
fun createCredentialEntryInfo(
userName: String,
+ displayName: String? = null,
credentialType: CredentialType = CredentialType.PASSKEY,
lastUsedTimeMillis: Long = 0L
): CredentialEntryInfo =
@@ -188,7 +224,7 @@
credentialTypeDisplayName = "",
providerDisplayName = "",
userName = userName,
- displayName = "",
+ displayName = displayName,
icon = mDrawable,
shouldTintIcon = false,
lastUsedTimeMillis = Instant.ofEpochMilli(lastUsedTimeMillis),
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/FlowEngine.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/FlowEngine.kt
index b2f55c1..2f5ec72 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/FlowEngine.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/FlowEngine.kt
@@ -81,12 +81,12 @@
) : Get()
/** Getting credential UI state on secondary screen when there are multiple accounts available. */
data class MultipleEntry(
- val accounts: List<PerUserNameEntries>,
+ val accounts: List<PerNameEntries>,
val actionEntryList: List<ActionEntryInfo>,
val authenticationEntryList: List<AuthenticationEntryInfo>,
) : Get() {
- data class PerUserNameEntries(
- val userName: String,
+ data class PerNameEntries(
+ val name: String,
val sortedCredentialEntryList: List<CredentialEntryInfo>,
)
}
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt
index a75aeaf..d6e19a6 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt
@@ -104,7 +104,6 @@
scrollable(Screen.MultipleCredentialsScreenFlatten.route) {
MultiCredentialsFlattenScreen(
credentialSelectorUiState = (remember { uiState } as MultipleEntry),
- columnState = it.columnState,
flowEngine = flowEngine,
)
}
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/CredentialsScreenChip.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/CredentialsScreenChip.kt
index 25bc381..e58de64 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/CredentialsScreenChip.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/CredentialsScreenChip.kt
@@ -19,10 +19,11 @@
import androidx.compose.foundation.layout.Row
import androidx.compose.material3.Icon
import android.graphics.drawable.Drawable
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material.icons.outlined.LockOpen
@@ -62,7 +63,7 @@
WearButtonText(
text = label,
textAlign = textAlign,
- maxLines = if (secondaryLabel != null) 1 else 2
+ maxLines = 2
)
},
secondaryLabel,
@@ -88,7 +89,13 @@
) {
val labelParam: (@Composable RowScope.() -> Unit) =
{
- text()
+ var horizontalArrangement = Arrangement.Start
+ if (icon == null) {
+ horizontalArrangement = Arrangement.Center
+ }
+ Row(horizontalArrangement = horizontalArrangement, modifier = modifier.fillMaxWidth()) {
+ text()
+ }
}
val secondaryLabelParam: (@Composable RowScope.() -> Unit)? =
@@ -97,6 +104,7 @@
Row {
WearSecondaryLabel(
text = secondaryLabel,
+ color = WearMaterialTheme.colors.onSurfaceVariant
)
if (isAuthenticationEntryLocked != null) {
@@ -178,6 +186,7 @@
WearButtonText(
text = stringResource(R.string.dialog_continue_button),
textAlign = TextAlign.Center,
+ color = WearMaterialTheme.colors.surface,
)
},
colors = ChipDefaults.primaryChipColors(),
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/SignInHeader.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/SignInHeader.kt
index 0afef5e..a82360b 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/SignInHeader.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/SignInHeader.kt
@@ -16,9 +16,11 @@
package com.android.credentialmanager.ui.components
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
import android.graphics.drawable.Drawable
import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
@@ -36,26 +38,30 @@
icon: Drawable?,
title: String,
) {
- Column(
- modifier = Modifier,
- horizontalAlignment = Alignment.CenterHorizontally
- ) {
- if (icon != null) {
- Icon(
- bitmap = icon.toBitmap().asImageBitmap(),
- modifier = Modifier.size(24.dp),
- // Decorative purpose only.
- contentDescription = null,
- tint = Color.Unspecified,
+ Row {
+ Spacer(Modifier.weight(0.073f)) // 7.3% side margin
+ Column(
+ modifier = Modifier.weight(0.854f).fillMaxSize(),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ if (icon != null) {
+ Icon(
+ bitmap = icon.toBitmap().asImageBitmap(),
+ modifier = Modifier.size(24.dp),
+ // Decorative purpose only.
+ contentDescription = null,
+ tint = Color.Unspecified,
+ )
+ }
+ Spacer(modifier = Modifier.size(8.dp))
+
+ WearTitleText(
+ text = title,
)
+
+ Spacer(modifier = Modifier.size(8.dp))
}
- Spacer(modifier = Modifier.size(8.dp))
-
- WearTitleText(
- text = title,
- )
-
- Spacer(modifier = Modifier.size(8.dp))
+ Spacer(Modifier.weight(0.073f)) // 7.3% side margin
}
}
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/Texts.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/Texts.kt
index 282fea0..a7b13ad 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/Texts.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/Texts.kt
@@ -16,6 +16,7 @@
package com.android.credentialmanager.common.ui.components
+import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.Text
@@ -43,7 +44,7 @@
Text(
modifier = modifier.wrapContentSize(),
text = text,
- color = WearMaterialTheme.colors.onSurfaceVariant,
+ color = WearMaterialTheme.colors.onSurface,
textAlign = TextAlign.Center,
overflow = TextOverflow.Ellipsis,
maxLines = 2,
@@ -60,7 +61,7 @@
Text(
modifier = modifier.padding(start = 8.dp, end = 8.dp).wrapContentSize(),
text = text,
- color = WearMaterialTheme.colors.onSurfaceVariant,
+ color = WearMaterialTheme.colors.onSurface,
style = WearMaterialTheme.typography.caption1,
overflow = TextOverflow.Ellipsis,
textAlign = textAlign,
@@ -91,12 +92,13 @@
@Composable
fun WearSecondaryLabel(
text: String,
- modifier: Modifier = Modifier,
+ color: Color = WearMaterialTheme.colors.onSurface,
+ modifier: Modifier = Modifier
) {
Text(
- modifier = modifier.wrapContentSize(),
+ modifier = modifier.fillMaxSize(),
text = text,
- color = WearMaterialTheme.colors.onSurfaceVariant,
+ color = color,
style = WearMaterialTheme.typography.caption1,
overflow = TextOverflow.Ellipsis,
textAlign = TextAlign.Start,
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/mappers/CredentialSelectorUiStateGetMapper.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/mappers/CredentialSelectorUiStateGetMapper.kt
index 2656275..7dfe742e 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/mappers/CredentialSelectorUiStateGetMapper.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/mappers/CredentialSelectorUiStateGetMapper.kt
@@ -19,15 +19,18 @@
import android.graphics.drawable.Drawable
import com.android.credentialmanager.model.Request
import com.android.credentialmanager.CredentialSelectorUiState
-import com.android.credentialmanager.CredentialSelectorUiState.Get.MultipleEntry.PerUserNameEntries
+import com.android.credentialmanager.CredentialSelectorUiState.Get.MultipleEntry.PerNameEntries
import com.android.credentialmanager.model.CredentialType
import com.android.credentialmanager.model.get.CredentialEntryInfo
import java.time.Instant
fun Request.Get.toGet(isPrimary: Boolean): CredentialSelectorUiState.Get {
+
val accounts = providerInfos
.flatMap { it.credentialEntryList }
- .groupBy { it.userName}
+ .groupBy {
+ if (it.displayName.isNullOrBlank()) it.userName else checkNotNull(it.displayName)
+ }
.entries
.toList()
@@ -56,7 +59,7 @@
}
} else {
CredentialSelectorUiState.Get.MultipleEntry(
- accounts = accounts.map { PerUserNameEntries(
+ accounts = accounts.map { PerNameEntries(
it.key,
it.value.sortedWith(comparator)
)
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFlattenScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFlattenScreen.kt
index 36e9792..ef32c94 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFlattenScreen.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFlattenScreen.kt
@@ -15,14 +15,18 @@
*/
package com.android.credentialmanager.ui.screens.multiple
-import com.android.credentialmanager.ui.components.CredentialsScreenChip
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
+import com.android.credentialmanager.ui.components.CredentialsScreenChip
+import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.Alignment
import com.android.credentialmanager.CredentialSelectorUiState.Get.MultipleEntry
import com.android.credentialmanager.FlowEngine
import com.android.credentialmanager.R
@@ -32,13 +36,13 @@
import com.android.credentialmanager.ui.components.CredentialsScreenChipSpacer
import com.google.android.horologist.annotations.ExperimentalHorologistApi
import com.google.android.horologist.compose.layout.ScalingLazyColumn
-import com.google.android.horologist.compose.layout.ScalingLazyColumnState
+import com.google.android.horologist.compose.layout.rememberColumnState
+import com.google.android.horologist.compose.layout.ScalingLazyColumnDefaults
/**
* Screen that shows multiple credentials to select from, grouped by accounts
*
* @param credentialSelectorUiState The app bar view model.
- * @param columnState ScalingLazyColumn configuration to be be applied
* @param modifier styling for composable
* @param flowEngine [FlowEngine] that updates ui state for this screen
*/
@@ -46,28 +50,45 @@
@Composable
fun MultiCredentialsFlattenScreen(
credentialSelectorUiState: MultipleEntry,
- columnState: ScalingLazyColumnState,
flowEngine: FlowEngine,
) {
val selectEntry = flowEngine.getEntrySelector()
- ScalingLazyColumn(
- columnState = columnState,
- modifier = Modifier.fillMaxSize(),
- ) {
+ Row {
+ Spacer(Modifier.weight(0.052f)) // 5.2% side margin
+ ScalingLazyColumn(
+ columnState = rememberColumnState(
+ ScalingLazyColumnDefaults.belowTimeText(horizontalAlignment = Alignment.Start),
+ ),
+ modifier = Modifier.weight(0.896f).fillMaxSize(), // 5.2% side margin
+ ) {
+
item {
- // make this credential specific if all credentials are same
- WearButtonText(
- text = stringResource(R.string.sign_in_options_title),
- textAlign = TextAlign.Start,
- )
+ Row {
+ Spacer(Modifier.weight(0.073f)) // 7.3% side margin
+ WearButtonText(
+ text = stringResource(R.string.sign_in_options_title),
+ textAlign = TextAlign.Center,
+ modifier = Modifier.weight(0.854f).fillMaxSize(),
+ )
+ Spacer(Modifier.weight(0.073f)) // 7.3% side margin
+ }
}
credentialSelectorUiState.accounts.forEach { userNameEntries ->
item {
- WearSecondaryLabel(
- text = userNameEntries.userName,
- modifier = Modifier.padding(top = 12.dp, bottom = 4.dp)
- )
+ Row {
+ Spacer(Modifier.weight(0.0624f)) // 6.24% side margin
+ WearSecondaryLabel(
+ text = userNameEntries.name,
+ modifier = Modifier.padding(
+ top = 12.dp,
+ bottom = 4.dp,
+ start = 0.dp,
+ end = 0.dp
+ ).fillMaxWidth(0.87f)
+ )
+ Spacer(Modifier.weight(0.0624f)) // 6.24% side margin
+ }
}
userNameEntries.sortedCredentialEntryList.forEach { credential: CredentialEntryInfo ->
@@ -78,7 +99,7 @@
secondaryLabel =
credential.credentialTypeDisplayName.ifEmpty {
credential.providerDisplayName
- },
+ },
icon = credential.icon,
textAlign = TextAlign.Start
)
@@ -87,14 +108,25 @@
}
}
}
- item {
- WearSecondaryLabel(
- text = stringResource(R.string.provider_list_title),
- modifier = Modifier.padding(top = 12.dp, bottom = 4.dp)
- )
- }
- credentialSelectorUiState.actionEntryList.forEach { actionEntry ->
+
+ if (credentialSelectorUiState.actionEntryList.isNotEmpty()) {
item {
+ Row {
+ Spacer(Modifier.weight(0.0624f)) // 6.24% side margin
+ WearSecondaryLabel(
+ text = stringResource(R.string.provider_list_title),
+ modifier = Modifier.padding(
+ top = 12.dp,
+ bottom = 4.dp,
+ start = 0.dp,
+ end = 0.dp
+ ).fillMaxWidth(0.87f)
+ )
+ Spacer(Modifier.weight(0.0624f)) // 6.24% side margin
+ }
+ }
+ credentialSelectorUiState.actionEntryList.forEach { actionEntry ->
+ item {
CredentialsScreenChip(
label = actionEntry.title,
onClick = { selectEntry(actionEntry, false) },
@@ -102,7 +134,10 @@
icon = actionEntry.icon,
)
CredentialsScreenChipSpacer()
+ }
}
}
}
+ Spacer(Modifier.weight(0.052f)) // 5.2% side margin
+ }
}
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFoldScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFoldScreen.kt
index ce2bad0..38307b0 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFoldScreen.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFoldScreen.kt
@@ -16,10 +16,12 @@
package com.android.credentialmanager.ui.screens.multiple
-import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.Row
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.foundation.layout.fillMaxSize
import com.android.credentialmanager.R
import androidx.compose.ui.res.stringResource
-import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@@ -53,29 +55,31 @@
flowEngine: FlowEngine,
) {
val selectEntry = flowEngine.getEntrySelector()
- ScalingLazyColumn(
- columnState = columnState,
- modifier = Modifier.fillMaxSize(),
- ) {
- // flatten all credentials into one
- val credentials = credentialSelectorUiState.sortedEntries
- item {
- var title = stringResource(R.string.choose_sign_in_title)
- if (credentials.isNotEmpty()) {
- if (credentials.all { it.credentialType == CredentialType.PASSKEY }) {
- title = stringResource(R.string.choose_passkey_title)
- } else if (credentials.all { it.credentialType == CredentialType.PASSWORD }) {
- title = stringResource(R.string.choose_password_title)
+ Row {
+ Spacer(Modifier.weight(0.052f)) // 5.2% side margin
+ ScalingLazyColumn(
+ columnState = columnState,
+ modifier = Modifier.weight(0.896f).fillMaxSize(),
+ ) {
+ // flatten all credentials into one
+ val credentials = credentialSelectorUiState.sortedEntries
+ item {
+ var title = stringResource(R.string.choose_sign_in_title)
+ if (credentials.isNotEmpty()) {
+ if (credentials.all { it.credentialType == CredentialType.PASSKEY }) {
+ title = stringResource(R.string.choose_passkey_title)
+ } else if (credentials.all { it.credentialType == CredentialType.PASSWORD }) {
+ title = stringResource(R.string.choose_password_title)
+ }
}
+
+ SignInHeader(
+ icon = credentialSelectorUiState.icon,
+ title = title,
+ )
}
- SignInHeader(
- icon = credentialSelectorUiState.icon,
- title = title,
- )
- }
-
- credentials.forEach { credential: CredentialEntryInfo ->
+ credentials.forEach { credential: CredentialEntryInfo ->
item {
CredentialsScreenChip(
label = credential.userName,
@@ -85,29 +89,32 @@
credential.providerDisplayName
},
icon = credential.icon,
+ textAlign = TextAlign.Start
)
CredentialsScreenChipSpacer()
}
}
- credentialSelectorUiState.authenticationEntryList.forEach { authenticationEntryInfo ->
- item {
- LockedProviderChip(authenticationEntryInfo) {
- selectEntry(authenticationEntryInfo, false)
+ credentialSelectorUiState.authenticationEntryList.forEach { authenticationEntryInfo ->
+ item {
+ LockedProviderChip(authenticationEntryInfo) {
+ selectEntry(authenticationEntryInfo, false)
+ }
+ CredentialsScreenChipSpacer()
}
- CredentialsScreenChipSpacer()
+ }
+ item {
+ Spacer(modifier = Modifier.size(8.dp))
+ }
+
+ item {
+ SignInOptionsChip { flowEngine.openSecondaryScreen() }
+ }
+ item {
+ DismissChip { flowEngine.cancel() }
+ BottomSpacer()
}
}
- item {
- Spacer(modifier = Modifier.size(8.dp))
+ Spacer(Modifier.weight(0.052f)) // 5.2% side margin
}
-
- item {
- SignInOptionsChip { flowEngine.openSecondaryScreen() }
- }
- item {
- DismissChip { flowEngine.cancel() }
- BottomSpacer()
- }
- }
}
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/SingleAccountScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/SingleAccountScreen.kt
index e94dd68..17dd962 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/SingleAccountScreen.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/SingleAccountScreen.kt
@@ -18,6 +18,8 @@
package com.android.credentialmanager.ui.screens.single
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@@ -31,15 +33,18 @@
headerContent: @Composable () -> Unit,
accountContent: @Composable () -> Unit,
columnState: ScalingLazyColumnState,
- modifier: Modifier = Modifier,
content: ScalingLazyListScope.() -> Unit,
) {
- ScalingLazyColumn(
- columnState = columnState,
- modifier = modifier.fillMaxSize(),
- ) {
- item { headerContent() }
- item { accountContent() }
- content()
+ Row {
+ Spacer(Modifier.weight(0.052f)) // 5.2% side margin
+ ScalingLazyColumn(
+ columnState = columnState,
+ modifier = Modifier.weight(0.896f).fillMaxSize(),
+ ) {
+ item { headerContent() }
+ item { accountContent() }
+ content()
+ }
+ Spacer(Modifier.weight(0.052f)) // 5.2% side margin
}
}
\ No newline at end of file
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/passkey/SinglePasskeyScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/passkey/SinglePasskeyScreen.kt
index 03608a4..ce243b0 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/passkey/SinglePasskeyScreen.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/passkey/SinglePasskeyScreen.kt
@@ -19,11 +19,8 @@
package com.android.credentialmanager.ui.screens.single.passkey
import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.unit.dp
import com.android.credentialmanager.FlowEngine
import com.android.credentialmanager.model.get.CredentialEntryInfo
import com.android.credentialmanager.R
@@ -75,7 +72,6 @@
}
},
columnState = columnState,
- modifier = Modifier.padding(horizontal = 10.dp)
) {
item {
val selectEntry = flowEngine.getEntrySelector()
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt
index 818723b..5bc4796 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt
@@ -19,11 +19,8 @@
package com.android.credentialmanager.ui.screens.single.password
import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.unit.dp
import com.android.credentialmanager.FlowEngine
import com.android.credentialmanager.R
import com.android.credentialmanager.ui.components.PasswordRow
@@ -67,7 +64,6 @@
)
},
columnState = columnState,
- modifier = Modifier.padding(horizontal = 10.dp)
) {
item {
Column {
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/signInWithProvider/SignInWithProviderScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/signInWithProvider/SignInWithProviderScreen.kt
index 34d6e97..14cc9bf 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/signInWithProvider/SignInWithProviderScreen.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/signInWithProvider/SignInWithProviderScreen.kt
@@ -17,10 +17,7 @@
package com.android.credentialmanager.ui.screens.single.signInWithProvider
import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.unit.dp
import com.android.credentialmanager.FlowEngine
import com.android.credentialmanager.model.get.CredentialEntryInfo
import com.android.credentialmanager.ui.components.AccountRow
@@ -47,7 +44,6 @@
fun SignInWithProviderScreen(
entry: CredentialEntryInfo,
columnState: ScalingLazyColumnState,
- modifier: Modifier = Modifier,
flowEngine: FlowEngine,
) {
SingleAccountScreen(
@@ -59,20 +55,19 @@
},
accountContent = {
val displayName = entry.displayName
- if (displayName == null ||
+ if (displayName.isNullOrBlank() ||
entry.displayName.equals(entry.userName, ignoreCase = true)) {
AccountRow(
primaryText = entry.userName,
)
} else {
AccountRow(
- primaryText = displayName,
- secondaryText = entry.userName,
+ primaryText = entry.userName,
+ secondaryText = displayName,
)
}
},
columnState = columnState,
- modifier = modifier.padding(horizontal = 10.dp)
) {
item {
val selectEntry = flowEngine.getEntrySelector()
diff --git a/packages/PackageInstaller/res/values-ar/strings.xml b/packages/PackageInstaller/res/values-ar/strings.xml
index de91c09..a82f982 100644
--- a/packages/PackageInstaller/res/values-ar/strings.xml
+++ b/packages/PackageInstaller/res/values-ar/strings.xml
@@ -66,9 +66,9 @@
<string name="archive_application_text_current_user_private_profile" msgid="1958423158655599132">"هل تريد أرشفة هذا التطبيق المحفوظ في المساحة الخاصّة؟ سيتم حفظ بياناتك الشخصية."</string>
<string name="uninstall_application_text_all_users" msgid="575491774380227119">"هل تريد إزالة هذا التطبيق "<b>"لكل"</b>" المستخدمين؟ ستتم إزالة التطبيق وبياناته من "<b>"كل"</b>" المستخدمين على هذا الجهاز."</string>
<string name="uninstall_application_text_user" msgid="498072714173920526">"هل تريد إزالة هذا التطبيق للمستخدم <xliff:g id="USERNAME">%1$s</xliff:g>؟"</string>
- <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"هل تريد إزالة تثبيت هذا التطبيق من ملفك الشخصي للعمل؟"</string>
+ <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"هل تريد إزالة تثبيت هذا التطبيق من ملف العمل الخاص بك؟"</string>
<string name="uninstall_update_text" msgid="863648314632448705">"هل تريد استبدال هذا التطبيق بإصدار المصنع؟ ستتم إزالة جميع البيانات."</string>
- <string name="uninstall_update_text_multiuser" msgid="8992883151333057227">"هل تريد إعادة ضبط هذا التطبيق على الإعدادات الأصلية؟ سؤدي ذلك إلى إزالة جميع البيانات، كما سيؤثر على جميع مستخدمي هذا الجهاز، بما في ذلك من لديهم ملفات شخصية للعمل."</string>
+ <string name="uninstall_update_text_multiuser" msgid="8992883151333057227">"هل تريد إعادة ضبط هذا التطبيق على الإعدادات الأصلية؟ سؤدي ذلك إلى إزالة جميع البيانات، كما سيؤثر على جميع مستخدمي هذا الجهاز، بما في ذلك من لديهم ملفات للعمل."</string>
<string name="uninstall_keep_data" msgid="7002379587465487550">"الاحتفاظ بـ <xliff:g id="SIZE">%1$s</xliff:g> من بيانات التطبيق."</string>
<string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"هل تريد حذف هذا التطبيق؟"</string>
<string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"هل تريد إلغاء تثبيت هذا التطبيق؟ سيتم أيضًا حذف نسخة \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\" الطبق الأصل."</string>
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/EdgeToEdgeUtils.java b/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/EdgeToEdgeUtils.java
index 6e53012..062e9b8 100644
--- a/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/EdgeToEdgeUtils.java
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/EdgeToEdgeUtils.java
@@ -36,7 +36,7 @@
* Enable Edge to Edge and handle overlaps using insets. It should be called before
* setContentView.
*/
- static void enable(@NonNull ComponentActivity activity) {
+ public static void enable(@NonNull ComponentActivity activity) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
return;
}
diff --git a/packages/SettingsLib/aconfig/settingslib.aconfig b/packages/SettingsLib/aconfig/settingslib.aconfig
index 83a986b1..754d9423 100644
--- a/packages/SettingsLib/aconfig/settingslib.aconfig
+++ b/packages/SettingsLib/aconfig/settingslib.aconfig
@@ -9,16 +9,6 @@
}
flag {
- name: "enable_cached_bluetooth_device_dedup"
- namespace: "bluetooth"
- description: "Enable dedup in CachedBluetoothDevice"
- bug: "319197962"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "bluetooth_qs_tile_dialog_auto_on_toggle"
namespace: "bluetooth"
description: "Displays the auto on toggle in the bluetooth QS tile dialog"
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 193d0bc..e612229 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Maak dat enige program na eksterne berging geskryf kan word, ongeag manifeswaardes"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Dwing aktiwiteite om verstelbaar te wees"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Maak die groottes van alle aktiwiteite verstelbaar vir veelvuldige vensters, ongeag manifeswaardes."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Aktiveer vryevormvensters (vorige)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Aktiveer steun vir eksperimentele vorige vryevormvensters."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Aktiveer vormvrye vensters"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Werkskerm-rugsteunwagwoord"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Volle rekenaarrugsteune word nie tans beskerm nie"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tik om die wagwoord vir volledige rekenaarrugsteune te verander of te verwyder"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> oor tot vol"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> oor tot vol"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Laaiproses word geoptimeer"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Laai tans"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Volgelaai teen <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Volgelaai teen <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 606a01c..7556de6 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"የዝርዝር ሰነዶች እሴቶች ግምት ውስጥ ሳያስገባ ማንኛውም መተግበሪያ ወደ ውጫዊ ማከማቻው ለመጻፍ ብቁ ያደርጋል"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"እንቅስቃሴዎች ዳግመኛ እንዲመጣጠኑ አስገድድ"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"የዝርዝር ሰነድ እሴቶች ምንም ይሁኑ ምን ለበርካታ መስኮቶች ሁሉንም እንቅስቃሴዎች መጠናቸው የሚቀየሩ እንዲሆኑ ያደርጋቸዋል።"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"ነፃ ቅርጽ መስኮቶች (የቆየ) ያንቁ"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"የሙከራ የቆዩ የነፃ ቅርጽ መስኮቶች ድጋፍን ያንቁ።"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"የነጻ ቅርጽ መስኮቶችን ያንቁ"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"የዴስክቶፕ መጠባበቂያ ይለፍ ቃል"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ዴስክቶፕ ሙሉ ምትኬዎች በአሁኑ ሰዓት አልተጠበቁም"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"የዴስክቶፕ ሙሉ ምትኬዎች የይለፍ ቃሉን ለመለወጥ ወይም ለማስወገድ ነካ ያድርጉ"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"እስኪሞላ ድረስ <xliff:g id="TIME">%1$s</xliff:g> ይቀራል"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - እስኪሞላ ድረስ <xliff:g id="TIME">%2$s</xliff:g> ይቀራል"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ኃይል መሙላት እንዲተባ ተደርጓል"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ኃይል በመሙላት ላይ"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - እስከ <xliff:g id="TIME">%3$s</xliff:g> ድረስ ይሞላል"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - እስከ <xliff:g id="TIME">%2$s</xliff:g> ሙሉ ለሙሉ ይሞላል"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 287dfae..99abb2e 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"تأهيل أي تطبيق بحيث تتم كتابته على وحدة تخزين خارجية، بغض النظر عن قيم البيان"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"فرض إمكانية تغيير حجم الأنشطة"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"السماح بتغيير حجم جميع الأنشطة لتناسب تعدد النوافذ، بغض النظر عن قيم البيان"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"تفعيل النوافذ الحرة (القديمة)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"تفعيل عرض النوافذ الحرة التجريبية القديمة"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"تفعيل النوافذ الحرة"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"كلمة مرور احتياطية للكمبيوتر"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"النُسخ الاحتياطية الكاملة لسطح المكتب غير محمية في الوقت الحالي"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"انقر لتغيير كلمة مرور النسخ الاحتياطية الكاملة لسطح المكتب أو إزالتها."</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"يتبقّى <xliff:g id="TIME">%1$s</xliff:g> حتى اكتمال شحن البطارية"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - يتبقّى <xliff:g id="TIME">%2$s</xliff:g> حتى اكتمال شحن البطارية."</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - تم تحسين الشحن"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g>: جارٍ الشحن"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - سيكتمل الشحن بحلول <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - سيكتمل الشحن بحلول <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index da17f80..38600f4 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"মেনিফেষ্টৰ মান যিয়েই নহওক, বাহ্যিক ষ্ট’ৰেজত লিখিবলৈ যিকোনো এপক উপযুক্ত কৰি তোলে"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"বলেৰে কাৰ্যকলাপসমূহৰ আকাৰ সলনি কৰিব পৰা কৰক"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"মেনিফেষ্টৰ মান যিয়েই নহওক, মাল্টি-ৱিণ্ডৰ বাবে আটাইবোৰ কাৰ্যকলাপৰ আকাৰ সলনি কৰিব পৰা কৰক।"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"ফ্ৰীফৰ্ম ৱিণ্ড’ সক্ষম কৰ (লিগেচী)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"পৰীক্ষামূলক লিগেচী ফ্ৰীফৰ্ম ৱিণ্ড’ৰ সমৰ্থন সক্ষম কৰক।"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"ফ্ৰিফৰ্ম ৱিণ্ড\'জ সক্ষম কৰক"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ডেস্কটপ বেকআপ পাছৱৰ্ড"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ডেস্কটপৰ পূৰ্ণ বেকআপ এতিয়ালৈকে সংৰক্ষিত অৱস্থাত নাই"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ডেস্কটপ সম্পূৰ্ণ বেকআপৰ বাবে পাছৱৰ্ডটো সলনি কৰিবলৈ বা আঁতৰাবলৈ টিপক"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"সম্পূৰ্ণ হ’বলৈ <xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"সম্পূৰ্ণ হ’বলৈ <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - চাৰ্জিং অপ্টিমাইজ কৰা হৈছে"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ চাৰ্জ হৈ আছে"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>ৰ ভিতৰত সম্পূৰ্ণ হ’ব"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>ৰ ভিতৰত সম্পূৰ্ণৰূপে চাৰ্জ হ’ব"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 5ae1c6e..d41cf0e 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Manifest dəyərindən asılı olmayaraq tətbiqlərin xarici daşıyıcılarda saxlanmasına icazə verilsin"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Çoxpəncərəli rejimdə ölçü dəyişdirilməsi"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Manifest dəyərindən asılı olmayaraq çoxpəncərəli rejimdə pəncərə ölçüsünün dəyişdirilməsinə icazə verilsin"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"İxtiyari formada pəncərələri (köhnə) aktivləşdirin"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Təcrübi köhnə ixtiyari formada pəncərələr üçün dəstəyi aktivləşdirin."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"İxtiyari formada pəncərə yaradılsın"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Masaüstü rezerv parolu"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Masaüstü tam rezervlər hazırda qorunmayıblar."</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Masaüstünün tam rezerv kopyalanması üçün parolu dəyişmək və ya silmək üçün basın"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Tam şarj edilənədək <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - tam şarj edilənədək <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Şarj optimallaşdırılıb"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Şarj edilir"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> radələrinə qədər tam dolacaq"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> radələrinə qədər tam dolacaq"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 2b92c52..c576af5 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Omogućava upisivanje svih aplikacija u spoljnu memoriju, bez obzira na vrednosti manifesta"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Prinudno omogući promenu veličine aktivnosti"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Omogućava promenu veličine svih aktivnosti za režim sa više prozora, bez obzira na vrednosti manifesta."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Omogući prozore proizvoljnog formata (zastarelo)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Omogućava podršku za zastarele eksperimentalne prozore proizvoljnog formata."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Omogući prozore proizvoljnog formata"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Lozinka rezervne kopije za računar"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Rezervne kopije čitavog sistema trenutno nisu zaštićene"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Dodirnite da biste promenili ili uklonili lozinku za pravljenje rezervnih kopija čitavog sistema na računaru"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do kraja punjenja"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do kraja punjenja"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje je optimizovano"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Punjenje"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Potpuno napunjeno do <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Potpuno napunjeno do <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index e676fdf..9fd2af3 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Робіць любую праграму даступнай для запісу ў знешняе сховішча, незалежна ад значэнняў маніфеста"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Зрабіць вокны дзеянняў даступнымі для змены памеру"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Зрабіць усе віды дзейнасці даступнымі для змены памеру ў рэжыме некалькіх вокнаў, незалежна ад значэнняў маніфеста."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Уключыць адвольную форму вокнаў (устарэлая налада)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Уключыць падтрымку для эксперыментальнай адвольнай формы вокнаў (устарэлая налада)."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Уключыць адвольную форму вокнаў"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Пароль для рэз. копіі ПК"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Поўнае рэзервовае капіраванне працоўнага стала зараз не абаронена"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Краніце, каб змяніць або выдаліць пароль для поўнага рэзервовага капіравання працоўнага стала"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Да поўнай зарадкі засталося <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – да поўнай зарадкі засталося: <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Зарадка аптымізавана"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – зараджаецца"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Прылада зарадзіцца поўнасцю да <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Прылада зарадзіцца поўнасцю да <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index c64e2ea..462535b 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Всички приложения ще отговарят на условията да бъдат записвани във външното хранилище независимо от стойностите в манифеста"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Възможност за преоразмеряване на активностите"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Дава възможност за преоразмеряване на всички активности в режима за няколко прозореца независимо от стойностите в манифеста."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Актив. на прозорците в свободна форма (наследени)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Активиране на поддръжката за експерименталните наследени прозорци в свободна форма."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Активиране на прозорците в свободна форма"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Парола за резервни копия"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Понастоящем пълните резервни копия за настолен компютър не са защитени"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Докоснете, за да промените или премахнете паролата за пълни резервни копия на настолния компютър"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Оставащо време до пълно зареждане: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – Оставащо време до пълно зареждане: <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Зареждането е оптимизирано"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарежда се"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – ще се зареди напълно до <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – ще се зареди напълно до <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 531795a..cd53b67 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"ম্যানিফেস্ট মানের নির্বিশেষে যেকোনও অ্যাপকে এক্সটারনাল স্টোরেজে ইনস্টল করার উপযুক্ত বানায়"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"আকার পরিবর্তনযোগ্য করার জন্য ক্রিয়াকলাপগুলিকে জোর করুন"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"ম্যানিফেস্ট মানগুলির নির্বিশেষে মাল্টি-উইন্ডোর জন্য সমস্ত ক্রিয়াকলাপগুলির আকার পরিবর্তনযোগ্য করুন৷"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"ফ্রিফর্ম উইন্ডো (লিগ্যাসি) চালু করুন"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"এক্সপেরিমেন্টাল ফ্রিফর্ম উইন্ডোর জন্য সহায়তা চালু করুন।"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"ফ্রি-ফর্ম উইন্ডো চালু করুন"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ডেস্কটপ ব্যাকআপ পাসওয়ার্ড"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ডেস্কটপ পূর্ণ ব্যাকআপ বর্তমানে সুরক্ষিত নয়"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ডেস্কটপের সম্পূর্ণ ব্যাকআপের পাসওয়ার্ডটি পরিবর্তন করতে বা মুছে ফেলতে আলতো চাপুন"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g>-এ ব্যাটারি পুরো চার্জ হয়ে যাবে"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>-এ ব্যাটারি পুরো চার্জ হয়ে যাবে"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - চার্জিং অপ্টিমাইজ করা হয়েছে"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - চার্জ করা হচ্ছে"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>-এর মধ্যে পুরো চার্জ হয়ে যাবে"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>-এর মধ্যে পুরো চার্জ হয়ে যাবে"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 93b4ffb..5e35f1a 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Omogućava upisivanje svih aplikacija u vanjsku pohranu, bez obzira na prikazane vrijednosti"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Nametni aktivnostima mijenjanje veličina"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Omogućava mijenjanje veličine svih aktivnosti za prikaz s više prozora, bez obzira na prikazane vrijednosti"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Omogući prilagodljive prozore (staro)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Omogućite podršku za eksperimentalne stare prilagodljive prozore."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Omogući prozore nepravilnih oblika"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Lozinka sigurnosne kopije za računar"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Potpune sigurnosne kopije za računare trenutno nisu zaštićene"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Dodirnite da promijenite ili uklonite lozinku za potpune rezervne kopije s radne površine"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do potpune napunjenosti"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do potpune napunjenosti"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje je optimizirano"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Napunit će se do <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Potpuno napunjeno do <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 0e6b3d8..18e8720 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Permet que qualsevol aplicació es pugui escriure en un dispositiu d’emmagatzematge extern, independentment dels valors del manifest"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Força l\'ajust de la mida de les activitats"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permet ajustar la mida de totes les activitats per al mode multifinestra, independentment dels valors del manifest"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Activa les finestres amb format lliure (heretat)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Activa la compatibilitat amb les finestres de format lliure heretades i experimentals."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Activa les finestres amb format lliure"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Contrasenya per a còpies d\'ordinador"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Les còpies de seguretat completes d\'ordinador no estan protegides"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Toca per canviar o suprimir la contrasenya per a les còpies de seguretat completes de l\'ordinador"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> per completar la càrrega"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g>: càrrega optimitzada"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g>: s\'està carregant"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Càrrega completa a les <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Càrrega completa a les <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index b04c908..7ca98f7 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Každou aplikaci bude možné zapsat do externího úložiště, bez ohledu na hodnoty manifestu"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Vynutit možnost změny velikosti aktivit"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Umožní změnu velikosti všech aktivit na několik oken (bez ohledu na hodnoty manifestu)"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Aktivovat okna s volným tvarem (starší nastavení)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Aktivuje podporu starších experimentálních oken s volným tvarem."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Aktivovat okna s volným tvarem"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Heslo pro zálohy v počítači"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Úplné zálohy v počítači nejsou v současné době chráněny"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tuto možnost vyberte, chcete-li změnit nebo odebrat heslo pro úplné zálohy do počítače"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do úplného nabití"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – optimalizované nabíjení"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Nabíjení"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Úplné nabití: <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Úplné nabití: <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 6e526db..5564722 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Gør det muligt at overføre enhver app til et eksternt lager uafhængigt af manifestværdier"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Gennemtving, at aktiviteter kan tilpasses"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Tillad, at alle aktiviteter kan tilpasses flere vinduer uafhængigt af manifestværdier"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Aktivér vinduer i frit format (forældet)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Aktivér understøttelse af eksperimentelle forældede vinduer i frit format."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Aktivér vinduer i frit format"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Kode til lokal sikkerhedskopi"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Lokale komplette backups er i øjeblikket ikke beskyttet"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tryk for at skifte eller fjerne adgangskoden til fuld lokal sikkerhedskopiering"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Fuldt opladet om <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – fuldt opladet om <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – opladning er optimeret"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – oplades"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Opladet senest kl. <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Fuldt opladet senest kl. <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 504a9da..2fd683d 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Jede App kann, ungeachtet der Manifestwerte, in den externen Speicher geschrieben werden"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Aktivitätengröße darf immer angepasst werden"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Die Größe aller Aktivitäten darf, ungeachtet der Manifestwerte, für die Mehrfensterdarstellung angepasst werden"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Freiform-Fenster zulassen (Legacy)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Unterstützung für experimentelle Legacy-Freiform-Fenster aktivieren."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Freiform-Fenster zulassen"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Passwort für Desktop-Sicherung"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Vollständige Desktop-Sicherungen sind momentan nicht passwortgeschützt"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Zum Ändern oder Entfernen des Passworts für vollständige Desktop-Sicherungen tippen"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Voll in <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – voll in <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Laden wird optimiert"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Wird geladen"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Vollständig geladen in <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Vollständig geladen in <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index cad445f..4fdea21 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Κάνει κάθε εφαρμογή κατάλληλη για εγγραφή σε εξωτερικό αποθηκευτικό χώρο, ανεξάρτητα από τις τιμές του μανιφέστου"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Αναγκαστική δυνατότητα αλλαγής μεγέθους δραστηριοτήτων"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Να έχουν όλες οι δραστηριότητες δυνατότητα αλλαγής μεγέθους για την προβολή πολλαπλών παραθύρων, ανεξάρτητα από τις τιμές του μανιφέστου."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Ενεργ. παραθύρων ελεύθερης μορφής (παλαιού τύπου)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Ενεργοποίηση υποστήριξης για πειραματικά παράθυρα ελεύθερης μορφής παλαιού τύπου."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Ενεργοποίηση παραθύρων ελεύθερης μορφής"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Εφ/κός κωδικός desktop"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Τα πλήρη αντίγραφα ασφαλείας επιφάνειας εργασίας δεν προστατεύονται αυτή τη στιγμή"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Πατήστε για αλλαγή ή κατάργηση του κωδικού πρόσβασης για τα πλήρη αντίγραφα ασφαλείας επιφάνειας εργασίας"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Απομένουν <xliff:g id="TIME">%1$s</xliff:g> για πλήρη φόρτιση"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - Απομένουν <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Η φόρτιση βελτιστοποιήθηκε"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Φόρτιση"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Πλήρης φόρτιση στις <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Πλήρης φόρτιση στις <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index ad43664..bcffe2c 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Force activities to be resizeable"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Make all activities resizeable for multi-window, regardless of manifest values."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Enable freeform windows (legacy)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Enable support for experimental legacy freeform windows."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Enable freeform windows"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Desktop backup password"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Desktop full backups aren\'t currently protected"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tap to change or remove the password for desktop full backups"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimised"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – charging"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Full by <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Fully charged by <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index a77d6c6..df54ac11 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Force activities to be resizable"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Make all activities resizable for multi-window, regardless of manifest values."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Enable freeform windows (legacy)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Enable support for experimental legacy freeform windows."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Enable freeform windows"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Desktop backup password"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Desktop full backups aren’t currently protected"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tap to change or remove the password for desktop full backups"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimized"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Full by <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Fully charged by <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -661,7 +661,7 @@
<string name="guest_exit_dialog_title" msgid="1846494656849381804">"Exit guest mode?"</string>
<string name="guest_exit_dialog_message" msgid="1743218864242719783">"This will delete apps and data from the current guest session"</string>
<string name="grant_admin" msgid="4323199171790522574">"Yes, make them an admin"</string>
- <string name="not_grant_admin" msgid="3557849576157702485">"No, dont make them an admin"</string>
+ <string name="not_grant_admin" msgid="3557849576157702485">"No, don\'t make them an admin"</string>
<string name="guest_exit_dialog_button" msgid="1736401897067442044">"Exit"</string>
<string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Save guest activity?"</string>
<string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"You can save activity from the current session or delete all apps and data"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index ad43664..bcffe2c 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Force activities to be resizeable"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Make all activities resizeable for multi-window, regardless of manifest values."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Enable freeform windows (legacy)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Enable support for experimental legacy freeform windows."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Enable freeform windows"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Desktop backup password"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Desktop full backups aren\'t currently protected"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tap to change or remove the password for desktop full backups"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimised"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – charging"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Full by <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Fully charged by <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index ad43664..bcffe2c 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Force activities to be resizeable"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Make all activities resizeable for multi-window, regardless of manifest values."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Enable freeform windows (legacy)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Enable support for experimental legacy freeform windows."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Enable freeform windows"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Desktop backup password"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Desktop full backups aren\'t currently protected"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tap to change or remove the password for desktop full backups"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimised"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – charging"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Full by <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Fully charged by <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 8d6520f..fc4c8a0 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Force activities to be resizable"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Make all activities resizable for multi-window, regardless of manifest values."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Enable freeform windows (legacy)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Enable support for experimental legacy freeform windows."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Enable freeform windows"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Desktop backup password"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Desktop full backups aren’t currently protected"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tap to change or remove the password for desktop full backups"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimized"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Full by <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Fully charged by <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 8b22833..e146f49 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Cualquier app puede escribirse en un almacenamiento externo, sin importar los valores del manifiesto"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Forzar actividades para que cambien de tamaño"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permitir que todas las actividades puedan cambiar de tamaño para el modo multiventana, sin importar los valores del manifiesto."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Habilitar ventanas de formato libre (heredado)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Permitir la compatibilidad con ventanas de formato libre experimentales (heredado)"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Habilitar ventanas de forma libre"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Contraseñas"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Tus copias de seguridad de escritorio no están protegidas por contraseña"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Presiona para cambiar o quitar la contraseña de las copias de seguridad completas de tu escritorio."</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> para completar"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga optimizada"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Cargando"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Carga completa: <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga completa: <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 961c067..fdfb844 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Permite que cualquier aplicación se pueda escribir en un almacenamiento externo independientemente de los valores de manifiesto"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Forzar que las actividades puedan cambiar de tamaño"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permite que todas las actividades puedan cambiar de tamaño en multiventana independientemente de los valores de manifiesto"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Habilitar ventanas de forma libre (antiguo)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Habilita la compatibilidad con ventanas de forma libre antiguas y experimentales."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Habilitar ventanas de forma libre"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Contraseña para copias de ordenador"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Las copias de seguridad completas de ordenador no están protegidas"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Toca para cambiar o quitar la contraseña de las copias de seguridad completas del escritorio"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> hasta la carga completa"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> hasta la carga completa"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga optimizada"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Cargar"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Carga completa a las <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga completa a las <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 70b436c..cff38eb 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Lubab mis tahes rakendusi kirjutada välisesse salvestusruumi manifesti väärtustest olenemata"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Muuda tegevuste suurused muudetavaks"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Muudetakse kõigi tegevuste suurused mitme aknaga vaates muudetavaks (manifesti väärtustest olenemata)."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Luba vabas vormis aknad (pärand)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Lubatakse katseliste pärand vabas vormis akende tugi."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Luba vabas vormis aknad"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Arvutivarunduse parool"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Täielikud arvutivarundused pole praegu kaitstud"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Puudutage täielike arvutivarunduste parooli muutmiseks või eemaldamiseks"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Täislaadimiseks kulub <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – täislaadimiseks kulub <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – laadimine on optimeeritud"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – laadimine"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – täis kell <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – aku saab täis kell <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 1c80af8..622055e 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Aplikazioek kanpoko memorian idatz dezakete, ezarritako balioak kontuan izan gabe"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Behartu jardueren tamaina doitu ahal izatera"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Eman aukera jarduera guztien tamaina doitzeko, leiho batean baino gehiagotan erabili ahal izan daitezen, ezarritako balioak kontuan izan gabe"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Gaitu estilo libreko leihoak (aurreko bertsiokoak)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Onartu aurreko bertsioko estilo libreko leiho esperimentalak."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Gaitu estilo libreko leihoak"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Babeskopien pasahitz lokala"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Une honetan, ordenagailuko babeskopia osoak ez daude babestuta"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Ordenagailuko eduki guztiaren babeskopia egiteko erabiltzen den pasahitza aldatzeko edo kentzeko, sakatu hau"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> guztiz kargatu arte"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Kargatzeko modu optimizatua"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Kargatzen"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Ordu honetan kargatuko da guztiz: <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ordu honetan kargatuko da guztiz: <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 5e4d29a..f7279b1 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"بدون توجه به مقادیر آشکار، هر برنامهای را برای نوشتن در حافظه خارجی واجد شرایط میکند"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"اجبار فعالیتها به قابل تغییر اندازه بودن"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"بدون توجه به مقادیر مانیفست، اندازه همه فعالیتها برای حالت چند پنجرهای میتواند تغییر کند."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"فعال کردن پنجرههای با قالب آزاد (قدیمی)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"فعال کردن پشتیبانی از پنجرههای با قالب آزاد قدیمی آزمایشی."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"فعال کردن پنجرههای آزاد"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"گذرواژه پشتیبانگیری محلی"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"پشتیبانگیری کامل رایانه درحال حاضر محافظت نمیشود"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"برای تغییر یا حذف گذرواژه برای نسخههای پشتیبان کامل رایانهای تکضرب بزنید"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> تا شارژ کامل باقی مانده است"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل باقی مانده است"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - شارژ بهینه شده است"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - درحال شارژ"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - تا <xliff:g id="TIME">%3$s</xliff:g> کامل میشود"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - شارژ تا <xliff:g id="TIME">%2$s</xliff:g> کامل میشود"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index ad0cab3..03f6b0a 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Mahdollistaa sovelluksen tietojen tallentamisen ulkoiseen tallennustilaan luetteloarvoista riippumatta"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Pakota kaikki toiminnot hyväksymään koon muutos"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Pakota kaikki toiminnot hyväksymään koon muuttaminen usean ikkunan tilassa luettelon arvoista riippumatta"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Ota vapaamuotoiset ikkunat käyttöön (vanha)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Ota kokeellinen vapaamuotoisten ikkunoiden tuki käyttöön (vanha)."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Ota käyttöön vapaamuotoiset ikkunat"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Varmuuskop. salasana"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Tietokoneen kaikkien tietojen varmuuskopiointia ei ole tällä hetkellä suojattu"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Vaihda tai poista tietokoneen kaikkien tietojen varmuuskopioinnin salasana koskettamalla."</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> kunnes täynnä"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Lataus optimoitu"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ladataan"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Täynnä klo <xliff:g id="TIME">%3$s</xliff:g> mennessä"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ladattu täyteen klo <xliff:g id="TIME">%2$s</xliff:g> mennessä"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index e46d20a..04bcb6c 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Rend possible l\'enregistrement de toute appli sur un espace de stockage externe, indépendamment des valeurs du fichier manifeste"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Forcer les activités à être redimensionnables"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permet de redimensionner toutes les activités pour le mode multi-fenêtre, indépendamment des valeurs du fichier manifeste."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Activer fenêtres de forme libre (patrimoniales)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Activer la prise en charge des fenêtres de forme libre patrimoniales expérimentales."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Activer les fenêtres de forme libre"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Mot de passe sauvegarde PC"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Les sauvegardes complètes sur PC ne sont pas protégées actuellement"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Touchez pour modifier ou supprimer le mot de passe utilisé pour les sauvegardes complètes sur ordinateur."</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à la recharge complète"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la recharge complète)"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Recharge optimisée"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Recharge en cours…"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Recharge complète d\'ici <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Recharge complète d\'ici <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index c60e8ce..455fd23 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Autoriser l\'enregistrement de toute application sur un espace de stockage externe, indépendamment des valeurs du fichier manifeste"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Forcer le redimensionnement des activités"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Rendre toutes les activités redimensionnables pour le mode multifenêtre, indépendamment des valeurs du fichier manifeste"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Activer les anciennes fenêtres de forme libre"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Permet d\'activer la compatibilité avec les anciennes fenêtres de forme libre expérimentales."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Activer les fenêtres de forme libre"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Mot de passe de sauvegarde ordi"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Les sauvegardes complètes sur ordi ne sont actuellement pas protégées"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Appuyez pour modifier ou supprimer le mot de passe des sauvegardes complètes sur ordi."</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Chargée à 100 %% dans <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - chargée à 100 %% dans <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Recharge optimisée"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - En charge"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Complètement chargé d\'ici <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Complètement chargé dans <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 9f58bd4..7127ca8 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Permite que calquera aplicación compatible se poida escribir nun almacenamento externo, independentemente dos valores do manifesto"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Forzar o axuste do tamaño das actividades"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permite axustar o tamaño de todas as actividades para o modo multiventá, independentemente dos valores do manifesto"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Activar ventás de forma libre (antigas)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Activa a compatibilidade coas ventás de forma libre experimentais antigas."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Activar ventás de forma libre"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Contrasinal para copias"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"As copias de seguranza de ordenador completas non están protexidas"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Toca para cambiar ou quitar o contrasinal para as copias de seguranza completas de ordenador"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> para completar a carga"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> para completar a carga)"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> (carga optimizada)"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> (cargando)"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Completarase á/s <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga completa á/s <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index b44f0c7..f89e148 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"મેનિફેસ્ટ મૂલ્યોને ધ્યાનમાં લીધા સિવાય, કોઈપણ ઍપને બાહ્ય સ્ટોરેજ પર લખાવા માટે લાયક બનાવે છે"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"પ્રવૃત્તિઓને ફરીથી કદ યોગ્ય થવા માટે ફરજ પાડો"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"મૅનિફેસ્ટ મૂલ્યોને ધ્યાનમાં લીધા સિવાય, તમામ પ્રવૃત્તિઓને મલ્ટી-વિન્ડો માટે ફરીથી કદ બદલી શકે તેવી બનાવો."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"ફ્રીફોર્મ વિન્ડો ચાલુ કરો (જૂની)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"પ્રાયોગિક જૂની ફ્રીફોર્મ વિન્ડો માટે સપોર્ટ મેળવવાની સુવિધા ચાલુ કરો."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"ફ્રીફોર્મ વિન્ડો ચાલુ કરો"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ડેસ્કટૉપ બૅકઅપ પાસવર્ડ"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ડેસ્કટૉપ સંપૂર્ણ બૅકઅપ હાલમાં સુરક્ષિત નથી"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ડેસ્કટૉપ સંપૂર્ણ બેકઅપ્સ માટેનો પાસવર્ડ બદલવા અથવા દૂર કરવા માટે ટૅચ કરો"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"પૂર્ણ ચાર્જ થવામાં <xliff:g id="TIME">%1$s</xliff:g> બાકી છે"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - પૂર્ણ ચાર્જ થવામાં <xliff:g id="TIME">%2$s</xliff:g> બાકી છે"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ચાર્જિંગ ઑપ્ટિમાઇઝ કરવામાં આવ્યું છે"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ચાર્જિંગ"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> સુધીમાં સંપૂર્ણ ચાર્જ થશે"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> સુધીમાં સંપૂર્ણ ચાર્જ થશે"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 246f66e..adf8b5f 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"इससे कोई भी ऐप्लिकेशन बाहरी स्टोरेज में रखने लायक बन जाता है, चाहे उसकी मेनिफ़ेस्ट वैल्यू कुछ भी हो"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"विंडो के हिसाब से गतिविधियों का साइज़ बदल दें"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"सभी गतिविधियों को मल्टी-विंडो (एक से ज़्यादा ऐप्लिकेशन, एक साथ) के लिए साइज़ बदलने लायक बनाएं, चाहे उनकी मेनिफ़ेस्ट वैल्यू कुछ भी हो."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"फ़्रीफ़ॉर्म विंडो वाला लेगसी मोड चालू करें"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"एक्सपेरिमेंट के तौर पर उपलब्ध फ़्रीफ़ॉर्म विंडो वाला लेगसी मोड चालू करें."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"फ़्रीफ़ॉर्म विंडो (एक साथ कई विंडो दिखाना) चालू करें"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"डेस्कटॉप बैकअप पासवर्ड"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"डेस्कटॉप का पूरा बैकअप फ़िलहाल सुरक्षित नहीं है"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"डेस्कटॉप के पूरे बैक अप का पासवर्ड बदलने या हटाने के लिए टैप करें"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> में बैटरी पूरी चार्ज हो जाएगी"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> में बैटरी पूरी चार्ज हो जाएगी"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्जिंग को ऑप्टिमाइज़ किया गया"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्ज हो रही है"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - बैटरी <xliff:g id="TIME">%3$s</xliff:g> में पूरी चार्ज हो जाएगी"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - बैटरी <xliff:g id="TIME">%2$s</xliff:g> में पूरी चार्ज हो जाएगी"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index f4bb6ea..3c20bf4 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Aplikacije se mogu zapisivati u vanjsku pohranu neovisno o vrijednostima manifesta"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Nametni mogućnost promjene veličine za aktivnosti"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Omogući mijenjanje veličine svih aktivnosti za više prozora, neovisno o vrijednostima manifesta."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Omogući prozore slobodnog oblika (naslijeđeno)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Omogući podršku za eksperimentalne naslijeđene prozore slobodnog oblika."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Omogući prozore slobodnog oblika"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Zaporka sigurnosne kopije"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Potpune sigurnosne kopije na stolnom računalu trenutačno nisu zaštićene"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Dodirnite da biste promijenili ili uklonili zaporku za potpune sigurnosne kopije na računalu"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do napunjenosti"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napunjenosti"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje se optimizira"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – bit će pun do <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – potpuno napunjeno do <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index db739d5..fd938b9 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Lehetővé teszi bármely alkalmazás külső tárhelyre való írását a jegyzékértékektől függetlenül"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Tevékenységek átméretezésének kényszerítése"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Legyen az összes tevékenység átméretezhető a többablakos megjelenítés érdekében a jegyzékértékektől függetlenül."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Szabad formájú ablakok engedélyezése (régi)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Kísérleti, régi szabad formájú ablakok támogatásának engedélyezése."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Szabad formájú ablakok engedélyezése"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Asztali mentés jelszava"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Az asztali teljes biztonsági mentések jelenleg nem védettek."</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Koppintson ide az asztali teljes mentések jelszavának módosításához vagy eltávolításához"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> a teljes töltöttségig"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a teljes töltöttségig"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimalizált töltés"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Töltés…"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Teljes feltöltés eddig: <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Teljes feltöltés eddig: <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 717313fb..389aad2 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Թույլ է տալիս ցանկացած հավելված պահել արտաքին սարքում՝ մանիֆեստի արժեքներից անկախ"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Չափերի փոփոխում բազմապատուհան ռեժիմում"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Բոլոր ակտիվությունների չափերը բազմապատուհան ռեժիմի համար դարձնել փոփոխելի՝ մանիֆեստի արժեքներից անկախ:"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Միացնել կամայական ձևի պատուհանները (հնացած)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Միացնել կամայական ձևի պատուհանների ստեղծման հնացած փորձնական գործառույթի աջակցումը:"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Ակտիվացնել կամայական ձևի պատուհանները"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Աշխատասեղանի պահուստավորման գաղտնաբառ"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Աշխատասեղանի ամբողջական պահուստավորումները այժմ պաշտպանված չեն"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Հպեք՝ աշխատասեղանի ամբողջական պահուստավորման գաղտնաբառը փոխելու կամ հեռացնելու համար"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> մինչև լրիվ լիցքավորումը"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Լիցքավորումն օպտիմալացված է"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> — Լիցքավորում"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Ամբողջովին կլիցքավորվի մինչև <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ամբողջովին կլիցքավորվի մինչև <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 748d5ed..c6bd3e9 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Membuat semua aplikasi dapat ditulis ke penyimpanan eksternal, terlepas dari nilai manifes"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Paksa aktivitas agar ukurannya dapat diubah"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Membuat semua aktivitas dapat diubah ukurannya untuk banyak jendela, terlepas dari nilai manifes."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Aktifkan jendela freeform (versi lama)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Aktifkan dukungan untuk jendela freeform eksperimental versi lama."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Aktifkan jendela berformat bebas"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Sandi cadangan desktop"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Saat ini cadangan desktop penuh tidak dilindungi"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Ketuk guna mengubah atau menghapus sandi untuk cadangan lengkap desktop"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> lagi sampai penuh"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi sampai penuh"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pengisian daya dioptimalkan"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Mengisi daya"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Penuh pukul <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Baterai terisi penuh dalam <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 7871cb2..2575af0 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Gerir öll forrit skrifanleg í ytra geymslurými, óháð gildum í upplýsingaskrá"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Þvinga breytanlega stærð virkni"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Gera stærð allrar virkni breytanlega svo að hún henti fyrir marga glugga, óháð gildum í upplýsingaskrá."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Virkja glugga á frjálsu sniði (eldra)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Virkja stuðning við eldri tilraunaglugga á frjálsu sniði."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Virkja glugga með frjálsu sniði"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Aðgangsorð tölvuafritunar"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Heildarafritun á tölvu er ekki varin sem stendur."</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Ýttu til að breyta eða fjarlægja aðgangsorðið fyrir heildarafritun á tölvu"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> fram að fullri hleðslu"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> fram að fullri hleðslu"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Hleðsla fínstillt"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Í hleðslu"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Fullt kl. <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Fullhlaðið kl. <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 8ceaba0..deae4a5 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Consente l\'installazione di qualsiasi app su memoria esterna, indipendentemente dai valori manifest"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Imponi formato modificabile alle attività"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Rendi il formato di tutte le attività modificabile per la modalità multi-finestra, indipendentemente dai valori manifest"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Attiva finestre a forma libera (legacy)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Attiva il supporto delle finestre a forma libera sperimentali legacy."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Attiva finestre a forma libera"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Password di backup desktop"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"I backup desktop completi non sono attualmente protetti"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tocca per modificare o rimuovere la password per i backup desktop completi"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> alla ricarica completa"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla ricarica completa"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ricarica ottimizzata"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ In carica"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Ricarica completa entro <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batteria completamente carica entro <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index f7c9684..310b046 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"מאפשר כתיבה של כל אפליקציה באחסון חיצוני, ללא התחשבות בערכי המניפסט"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"אילוץ יכולת קביעת גודל של הפעילויות"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"מאפשר יכולת קביעת גודל של כל הפעילויות לריבוי חלונות, ללא התחשבות בערכי המניפסט."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"הפעלת שינוי הגודל והמיקום של החלונות (מדור קודם)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"הפעלת תמיכה בתכונה הניסיונית מדור קודם של שינוי הגודל והמיקום של החלונות."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"הפעלת האפשרות לשנות את הגודל והמיקום של החלונות"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"סיסמת גיבוי שולחן העבודה"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"גיבויים מלאים בשולחן העבודה אינם מוגנים כעת"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"יש להקיש כדי לשנות או להסיר את הסיסמה לגיבויים מלאים בשולחן העבודה"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"הזמן הנותר לטעינה מלאה: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – הזמן הנותר לטעינה מלאה: <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – הטעינה עברה אופטימיזציה"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – בטעינה"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – טעינה מלאה עד <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – טעינה מלאה עד <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index cafa95d..4dc0580 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"マニフェストの値に関係なく、すべてのアプリを外部ストレージに書き込めるようになります"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"アクティビティをサイズ変更可能にする"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"マニフェストの値に関係なく、マルチウィンドウですべてのアクティビティのサイズを変更できるようにします。"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"フリーフォーム ウィンドウを有効にする(従来版)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"従来の試験運用版のフリーフォーム ウィンドウのサポートを有効にします。"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"フリーフォーム ウィンドウを有効にする"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"PC バックアップ パスワード"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"デスクトップのフルバックアップは現在保護されていません"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"デスクトップのフルバックアップ用のパスワードを変更または削除する場合にタップします"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"完了まであと <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - 完了まであと <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電が最適化されています"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電中"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>までに完了"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>までに充電完了"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 10a660b..a196844 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -434,8 +434,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"აპები ჩაიწერება გარე მეხსიერებაზე აღწერის ფაილების მნიშვნელობების მიუხედავად"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"ზომაცვლადი აქტივობების იძულება"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"მანიფესტის მნიშვნელობების მიუხედავად, მრავალი ფანჯრის რეჟიმისთვის ყველა აქტივობის ზომაცვლადად გადაქცევა."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"თავისუფალი ფორმის ფანჯრების ჩართვა (მოძველებული)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"თავისუფალი ფორმის ექსპერიმენტული მოძველებული ფანჯრების ჩართვა."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"თავისუფალი ფორმის მქონე ფანჯრების ჩართვა"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"დესკტოპის სარეზერვო ასლის პაროლი"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"დესკტოპის სრული სარეზერვო ასლები ამჟამად დაცული არ არის"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"შეეხეთ დესკტოპის სრული სარეზერვო ასლების პაროლის შესაცვლელად ან წასაშლელად"</string>
@@ -500,7 +499,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"სრულ დატენვამდე დარჩენილია <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> — სრულ დატენვამდე დარჩენილია <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - დატენვა ოპტიმიზირებულია"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – იტენება"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - სრულად დატენის დრო: <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - სრულად დატენის დრო: <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 536b624..b0b71ef 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Манифест мәндеріне қарамастан, кез келген қолданбаны сыртқы жадқа жазуға рұқсат беру"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Әрекеттердің өлшемін өзгертуге рұқсат ету"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Манифест мәндеріне қарамастан, бірнеше терезе режимінде барлық әрекеттердің өлшемін өзгертуге рұқсат беру"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Еркін пішінді терезелерге рұқсат беру (бұрынғы)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Эксперименттік бұрынғы еркін пішінді терезелерді қолдауға рұқсат береді."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Еркін пішінді терезелерге рұқсат беру"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Компьютердегі сақтық көшірме құпия сөзі"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Компьютердегі толық сақтық көшірмелер қазір қорғалмаған."</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Үстелдік компьютердің толық сақтық көшірмелерінің кілтсөзін өзгерту немесе жою үшін түртіңіз"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Толық зарядталғанға дейін <xliff:g id="TIME">%1$s</xliff:g> қалды."</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: толық зарядталуға <xliff:g id="TIME">%2$s</xliff:g> қалды"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарядтау оңтайландырылды"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Зарядталып жатыр"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Зарядталып болады: <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Толық заряд алуға қалған уақыт: <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index baef5d8..577a2ae 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"ធ្វើឲ្យកម្មវិធីទាំងឡាយមានសិទ្ធិសរសេរទៅកាន់ឧបករណ៍ផ្ទុកខាងក្រៅ ដោយមិនគិតពីតម្លៃមេនីហ្វេសថ៍"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"បង្ខំឲ្យសកម្មភាពអាចប្តូរទំហំបាន"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"ធ្វើឲ្យសកម្មភាពទាំងអស់អាចប្តូរទំហំបានសម្រាប់ពហុវិនដូ ដោយមិនគិតពីតម្លៃមេនីហ្វេសថ៍។"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"បើកវិនដូទម្រង់សេរី (ចាស់)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"បើកជំនួយសម្រាប់វិនដូទម្រង់សេរីចាស់ក្នុងដំណាក់កាលពិសោធន៍។"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"បើកដំណើរការផ្ទាំងវិនដូទម្រង់សេរី"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ពាក្យសម្ងាត់បម្រុងទុកលើកុំព្យូទ័រ"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"បច្ចុប្បន្ន ការបម្រុងទុកពេញលេញនៅលើកុំព្យូទ័រមិនត្រូវបានការពារទេ"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ប៉ះដើម្បីប្ដូរ ឬយកពាក្យសម្ងាត់ចេញសម្រាប់ការបម្រុងទុកពេញលេញលើកុំព្យូទ័រ"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> ទៀតទើបពេញ"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - នៅសល់ <xliff:g id="TIME">%2$s</xliff:g> ទៀតទើបពេញ"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - បានបង្កើនប្រសិទ្ធភាពនៃការសាក"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - កំពុងសាកថ្ម"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - ពេញនៅម៉ោង <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - សាកថ្មពេញនៅម៉ោង <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index a203ea7..69e8bff 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"ಮ್ಯಾನಿಫೆಸ್ಟ್ ಮೌಲ್ಯಗಳು ಯಾವುದೇ ಆಗಿದ್ದರೂ, ಬಾಹ್ಯ ಸಂಗ್ರಹಣೆಗೆ ಬರೆಯಲು ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಅರ್ಹಗೊಳಿಸುತ್ತದೆ"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"ಚಟುವಟಿಕೆಗಳನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸುವಂತೆ ಒತ್ತಾಯ ಮಾಡಿ"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"ಮ್ಯಾನಿಫೆಸ್ಟ್ ಮೌಲ್ಯಗಳನ್ನು ಪರಿಗಣಿಸದೇ, ಬಹು-ವಿಂಡೊಗೆ ಎಲ್ಲಾ ಚಟುವಟಿಕೆಗಳನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸುವಂತೆ ಮಾಡಿ."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"ಫ್ರೀಫಾರ್ಮ್ ವಿಂಡೋಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ (ಲೆಗಸಿ)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"ಪ್ರಾಯೋಗಿಕ ಲೆಗಸಿ ಫ್ರೀಫಾರ್ಮ್ ವಿಂಡೋಗಳಿಗೆ ಬೆಂಬಲವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"ಮುಕ್ತಸ್ವರೂಪದ ವಿಂಡೊಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ಡೆಸ್ಕ್ಟಾಪ್ ಬ್ಯಾಕಪ್ ಪಾಸ್ವರ್ಡ್"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ಡೆಸ್ಕ್ಟಾಪ್ ಪೂರ್ಣ ಬ್ಯಾಕಪ್ಗಳನ್ನು ಪ್ರಸ್ತುತ ರಕ್ಷಿಸಲಾಗಿಲ್ಲ"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ಡೆಸ್ಕ್ಟಾಪ್ನ ಪೂರ್ಣ ಬ್ಯಾಕಪ್ಗಳಿಗೆ ಪಾಸ್ವರ್ಡ್ ಬದಲಾಯಿಸಲು ಅಥವಾ ತೆಗೆದುಹಾಕಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> - ಸಮಯದಲ್ಲಿ ಪೂರ್ತಿ ಚಾರ್ಜ್ ಆಗುತ್ತದೆ"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ಸಮಯದಲ್ಲಿ ಪೂರ್ತಿ ಚಾರ್ಜ್ ಆಗುತ್ತದೆ"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಚಾರ್ಜಿಂಗ್ ಅನ್ನು ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗಿದೆ"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಚಾರ್ಜಿಂಗ್ ಆಗುತ್ತಿದೆ"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> ವೇಳೆಗೆ ಭರ್ತಿಯಾಗುತ್ತದೆ"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ವೇಳೆಗೆ ಸಂಪೂರ್ಣವಾಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತದೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 67f1ecd..af4f37b 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"매니페스트 값과 관계없이 모든 앱이 외부 저장소에 작성되도록 허용"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"활동의 크기가 조정 가능하도록 설정"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"모든 활동을 매니페스트 값에 관계없이 멀티 윈도우용으로 크기 조정 가능하도록 설정"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"자유 형식 창 사용(레거시)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"실험적인 레거시 자유 형식 창에 대한 지원을 사용하도록 설정합니다."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"자유 형식 창 사용"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"데스크톱 백업 비밀번호"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"데스크톱 전체 백업에 비밀번호가 설정되어 있지 않음"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"데스크톱 전체 백업에 대한 비밀번호를 변경하거나 삭제하려면 탭하세요."</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> 후 충전 완료"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - 충전 최적화됨"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ 충전 중"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>에 완전히 충전됨"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>에 완전히 충전됨"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 7353264..95d35f3 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Манифест маанилерине карабастан бардык колдонмолорду тышкы сактагычка сактоого уруксат берет"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Бир нече терезе режиминде өлчөмдү өзгөртүү"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Бир нече терезе режиминде өлчөмдү өзгөртүүгө уруксат берет (манифесттин маанилерине карабастан)"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Эркин формадагы терезелерди түзүүнү иштетүү (эски)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Эркин формадагы эски терезелерди түзүү боюнча сынамык функциясы иштетилет."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Эркин формадагы терезелерди түзүүнү иштетүү"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Камдык көчүрмөнүн сырсөзү"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Толук камдык көчүрмөлөр учурда корголгон эмес"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Иш тактасынын камдалган сырсөзүн өзгөртүү же алып салуу үчүн таптап коюңуз"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> кийин толук кубатталат"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> кийин толук кубатталат"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> — Кубаттоо жакшыртылды"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Кубатталууда"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Саат <xliff:g id="TIME">%3$s</xliff:g> кубатталып бүтөт"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> чейин толук кубатталат"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 3680e8d..2bf96ad 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"ເຮັດໃຫ້ທຸກແອັບມີສິດໄດ້ຮັບການຂຽນໃສ່ພື້ນທີ່ຈັດເກັບຂໍ້ມູນພາຍນອກ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າ manifest"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"ບັງຄັງໃຫ້ການເຄື່ອນໄຫວປ່ຽນຂະໜາດໄດ້"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"ເຮັດໃຫ້ທຸກການເຄື່ອນໄຫວສາມາດປັບຂະໜາດໄດ້ສຳລັບຫຼາຍໜ້າຈໍ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າ manifest."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"ເປີດການນຳໃຊ້ໜ້າຈໍຮູບແບບອິດສະຫຼະ (ແບບເກົ່າ)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"ເປີດການນຳໃຊ້ການຮອງຮັບໜ້າຈໍຮູບແບບອິດສະຫຼະແບບເກົ່າເວີຊັນທົດລອງ."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"ເປີດໃຊ້ໜ້າຈໍຮູບແບບອິດສະຫຼະ"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ລະຫັດຜ່ານການສຳຮອງຂໍ້ມູນເດັສທັອບ"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ການສຳຮອງຂໍ້ມູນເຕັມຮູບແບບໃນເດັສທັອບຍັງບໍ່ໄດ້ຮັບການປ້ອງກັນໃນເວລານີ້"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ແຕະເພື່ອປ່ຽນ ຫຼື ລຶບລະຫັດຂອງການສຳຮອງຂໍ້ມູນເຕັມຮູບແບບໃນເດັສທັອບ"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"ຍັງເຫຼືອອີກ <xliff:g id="TIME">%1$s</xliff:g> ຈຶ່ງຈະສາກເຕັມ"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"ຍັງເຫຼືອອີກ <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈຶ່ງຈະສາກເຕັມ"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ການສາກຖືກປັບໃຫ້ເໝາະສົມແລ້ວ"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ກຳລັງສາກໄຟ"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - ຈະເຕັມພາຍໃນ <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - ຈະສາກເຕັມພາຍໃນ <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 4f0d6b0..6363cdb 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Nustatoma, kad visas programas būtų galima įrašyti į išorinę saugyklą, nepaisant aprašo verčių"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Priv. nust., kad veiksm. b. g. atl. kelių d. lang."</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Nustatyti, kad visus veiksmus būtų galima atlikti kelių dydžių languose, nepaisant aprašo verčių."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Įgalinti laisvos formos langus (pasenę)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Įgalinti eksperimentinių pasenusių laisvos formos langų palaikymą."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Įgalinti laisvos formos langus"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Viet. atsrg. kop. slapt."</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Šiuo metu visos vietinės atsarginės kopijos neapsaugotos"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Jei norite pakeisti ar pašalinti visų stalinio kompiuterio atsarginių kopijų slaptažodį, palieskite"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Liko <xliff:g id="TIME">%1$s</xliff:g>, kol bus visiškai įkrauta"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – liko <xliff:g id="TIME">%2$s</xliff:g>, kol bus visiškai įkrauta"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – įkrovimas optimizuotas"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – įkraunama"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – bus visiškai įkrauta <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – bus visiškai įkrauta <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index e571b84..2b82cdb 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Ļauj jebkuru lietotni ierakstīt ārējā krātuvē neatkarīgi no manifesta vērtības."</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Pielāgot darbības"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Pielāgot visas darbības vairāku logu režīmam neatkarīgi no vērtībām manifestā."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Iespējot brīvās formas logus (mantots režīms)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Iespējot atbalstu eksperimentālajam, mantotajam brīvās formas logu režīmam."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Iespējot brīvās formas logus"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Datora dublējuma parole"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Darbvirsmas pilnie dublējumi pašlaik nav aizsargāti."</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Pieskarieties, lai mainītu vai noņemtu paroli pilniem datora dublējumiem."</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> līdz pilnai uzlādei"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai uzlādei"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> — uzlāde optimizēta"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> — notiek uzlāde"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="STATUS">%2$s</xliff:g>. Tiks pilnībā uzlādēts līdz plkst. <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> — tiks pilnībā uzlādēts līdz plkst. <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index ab30556..b135afa 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Сите апликации ќе бидат подобни за запишување во надворешната меморија, независно од вредностите на манифестот"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Наметни променлива големина на активностите"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Сите активности ќе имаат променлива големина во режимот со повеќе прозорци, независно од вредностите на манифестот."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Овозможи прозорци со менлива големина (застарено)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Овозможете поддршка за експериментални застарени прозорци со менлива големина."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Овозможи прозорци со слободна форма"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Лозинка за бекап на компјутер"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Целосниот бекап на компјутерот во моментов не е заштитен"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Допрете за да се промени или отстрани лозинката за целосен бекап на компјутерот"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до полна батерија"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полна батерија"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – полнењето е оптимизирано"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – се полни"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Ќе се наполни целосно до <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ќе се наполни целосно до <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index d190691..5fa8961 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"മാനിഫെസ്റ്റ് മൂല്യങ്ങൾ പരിഗണിക്കാതെ, ബാഹ്യ സ്റ്റോറേജിലേക്ക് എഴുതപ്പെടുന്നതിന് ഏതൊരു ആപ്പിനെയും യോഗ്യമാക്കുന്നു"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"വലുപ്പം മാറ്റാൻ പ്രവർത്തനങ്ങളെ നിർബന്ധിക്കുക"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"മാനിഫെസ്റ്റ് മൂല്യങ്ങൾ പരിഗണിക്കാതെ, എല്ലാ ആക്ടിവിറ്റികളെയും മൾട്ടി-വിൻഡോയ്ക്കായി വലുപ്പം മാറ്റുക."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"ഫ്രീഫോം വിൻഡോകൾ പ്രവർത്തനക്ഷമമാക്കുക (ലെഗസി)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"പരീക്ഷണാത്മക ലെഗസി ഫ്രീഫോം വിൻഡോകൾക്കുള്ള പിന്തുണ പ്രവർത്തനക്ഷമമാക്കുക."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"ഫ്രീഫോം വിൻഡോകൾ പ്രവർത്തനക്ഷമമാക്കുക"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ഡെസ്ക്ടോപ്പ് ബാക്കപ്പ് പാസ്വേഡ്"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ഡെസ്ക്ടോപ്പ് പൂർണ്ണ ബാക്കപ്പുകൾ നിലവിൽ പരിരക്ഷിച്ചിട്ടില്ല"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ഡെസ്ക്ടോപ്പ് പൂർണ്ണ ബാക്കപ്പുകൾക്കായി പാസ്വേഡുകൾ മാറ്റാനോ നീക്കംചെയ്യാനോ ടാപ്പുചെയ്യുക"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"പൂർണ്ണമാകാൻ <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - പൂർണ്ണമാകാൻ <xliff:g id="TIME">%2$s</xliff:g> ശേഷിക്കുന്നു"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ചാർജിംഗ് ഒപ്റ്റിമൈസ് ചെയ്തു"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ ചാർജ് ചെയ്യുന്നു"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>-നകം പൂർണ്ണമാകും"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>-നകം പൂർണ്ണമായി ചാർജ് ചെയ്യും"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index c0a7939..388ea6f 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Манифест утгыг нь үл хамааран дурын апп-г гадаад санах ойд бичих боломжтой болгодог"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Үйл ажиллагааны хэмжээг өөрчилж болохуйц болгох"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Тодорхойлогч файлын утгыг үл хамааран, бүх үйл ажиллагааны хэмжээг олон цонхонд өөрчилж болохуйц болгоно уу."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Чөлөөт хэлбэрийн цонхыг идэвхжүүлэх (уламжлалт)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Туршилтын чөлөөт хэлбэрийн уламжлалт цонхны дэмжлэгийг идэвхжүүлнэ үү."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Чөлөөт хэлбэрийн цонхыг идэвхжүүлэх"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Компьютерын нөөцлөлтийн нууц үг"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Компьютерын бүрэн нөөцлөлт одоогоор хамгаалалтгүй байна"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Компьютерийн бүтэн нөөцлөлтийн нууц үгийг өөрчлөх, устгах бол дарна уу"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Дүүрэх хүртэл <xliff:g id="TIME">%1$s</xliff:g> үлдсэн"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - дүүрэх хүртэл <xliff:g id="TIME">%2$s</xliff:g> үлдсэн"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Цэнэглэх явцыг оновчилсон"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Цэнэглэж байна"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> гэхэд дүүрнэ"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> гэхэд бүрэн цэнэглэгдэнэ"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 4842a99..063b7d1 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"मॅनिफेस्ट मूल्ये काहीही असू देत, कोणत्याही अॅपला बाह्य स्टोरेजवर राइट करण्यासाठी पात्र बनविते"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"ॲक्टिव्हिटीचा आकार बदलण्यायोग्य होण्याची सक्ती करा"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"मॅनिफेस्ट मूल्ये काहीही असू देत, एकाहून अधिक विंडोसाठी सर्व अॅक्टिव्हिटीचा आकार बदलण्यायोग्य करा."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"फ्रीफॉर्म विंडो सुरू करा (लेगसी)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"प्रायोगिक लेगसी फ्रीफॉर्म विंडोसाठी सपोर्ट सुरू करा."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"freeform windows सुरू करा"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"डेस्कटॉप बॅकअप पासवर्ड"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"डेस्कटॉप पूर्ण बॅक अप सध्या संरक्षित नाहीत"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"डेस्कटॉपच्या पूर्ण बॅकअपसाठी असलेला पासवर्ड बदलण्यासाठी किंवा काढण्यासाठी टॅप करा"</string>
@@ -495,8 +494,9 @@
<string name="power_remaining_only_more_than_subtext" msgid="4873750633368888062">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> पेक्षा जास्त शिल्लक आहे"</string>
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"पूर्ण चार्ज होण्यासाठी <xliff:g id="TIME">%1$s</xliff:g> शिल्लक आहेत"</string>
- <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - पूर्ण चार्ज होण्यासाठी <xliff:g id="TIME">%2$s</xliff:g> शिल्लक आहे"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्जिंग ऑप्टिमाइझ केले"</string>
+ <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> या वेळेत बॅटरी पूर्ण चार्ज होईल"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ चार्ज होत आहे"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> पर्यंत पूर्ण होईल"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पर्यंत पूर्णपणे चार्ज होईल"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 01d6409..48ed79d 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Menjadikan sebarang apl layak ditulis ke storan luaran, tanpa mengambil kira nilai manifes"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Paksa aktiviti supaya boleh diubah saiz"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Bolehkan semua saiz aktiviti diubah untuk berbilang tetingkap, tanpa mengambil kira nilai manifes."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Dayakan tetingkap bentuk bebas (lama)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Dayakan sokongan untuk tetingkap bentuk bebas lama yang bersifat percubaan."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Dayakan tetingkap bentuk bebas"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Kata laluan sandaran desktop"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Sandaran penuh desktop tidak dilindungi pada masa ini"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Ketik untuk menukar atau mengalih keluar kata laluan untuk sandaran penuh desktop"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> lagi sebelum penuh"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi sebelum penuh"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pengecasan dioptimumkan"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Mengecas"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Penuh pada <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Dicas sepenuhnya pada <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 92b630d..d15a0be 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"သတ်မှတ်တန်ဖိုးများ မည်သို့ပင်ရှိစေ ပြင်ပသိုလှောင်ခန်းများသို့ မည်သည့်အက်ပ်ကိုမဆို ဝင်ရောက်ခွင့်ပြုသည်"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"လုပ်ဆောင်ချက်များ အရွယ်ပြောင်းနိုင်ခြင်း"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"သတ်မှတ်တန်ဖိုး မည်သို့ပင်ရှိစေ ဝင်းဒိုးများ၏ လုပ်ဆောင်မှုအားလုံးကို အရွယ်အစားပြင်သည်။"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"အလွတ်ပုံစံ ဝင်းဒိုးများ ဖွင့်ပါ (အဟောင်း)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"အလွတ်ပုံစံဝင်းဒိုးအဟောင်းများ စမ်းသပ်ရန် ပံ့ပိုးမှုရယူပါ။"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"ပုံစံမျိုးစုံ ဝင်းဒိုးများ ဖွင့်ရန်"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ဒက်စ်တော့ အရန်စကားဝှက်"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ဒက်စ်တော့ တစ်ခုလုံး အရန်သိမ်းဆည်းခြင်းကို လက်ရှိတွင် ကာကွယ်မထားပါ"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ဒက်စ်တော့ အပြည့်အဝ အရန်သိမ်းခြင်းအတွက် စကားဝှက်ကို ပြောင်းရန် သို့မဟုတ် ဖယ်ရှားရန် တို့ပါ။"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"အားပြည့်ရန် <xliff:g id="TIME">%1$s</xliff:g> လိုသည်"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားပြည့်ရန် <xliff:g id="TIME">%2$s</xliff:g> လိုသည်"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားသွင်းခြင်းကို အကောင်းဆုံးပြင်ဆင်ထားသည်"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားသွင်းနေသည်"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> တွင် အားပြည့်မည်"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> တွင် အားပြည့်မည်"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 75b04ad..8f5663a 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Dette gjør at alle apper kan lagres på eksterne lagringsmedier – uavhengig av manifestverdier"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Alle aktiviteter kan endre størrelse"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Gjør at alle aktiviteter kan endre størrelse for flervindusmodus, uavhengig av manifestverdier."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Slå på vinduer i fritt format (eldre versjon)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Slå på støtte for eldre versjon av vinduer i eksperimentelt fritt format."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Slå på vinduer i fritt format"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Passord for sikkerhetskopiering på datamaskin"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Fullstendig sikkerhetskopiering på datamaskin er ikke beskyttet"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Trykk for å endre eller fjerne passordet for fullstendige sikkerhetskopier på datamaskinen"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Fulladet om <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – Fulladet om <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ladingen er optimalisert"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – lader"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Fulladet innen <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Fulladet innen <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index b252854..ddb58d5 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"तोकिएको नियमको ख्याल नगरी एपलाई बाह्य भण्डारणमा चल्ने बनाउनुहोस्"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"बलपूर्वक एपहरूको आकार मिलाउन मिल्ने बनाउनुहोस्"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"तोकिएको नियमको ख्याल नगरी एपलाई एकभन्दा बढी विन्डोमा रिसाइज गर्न सकिने बनाउनुहोस्।"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"फ्रिफर्म विन्डोहरू अन गर्नुहोस् (लिगेसी)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"प्रयोगात्मक लिगेसी फ्रिफर्म विन्डोहरू चल्ने बनाउनुहोस्"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"फ्रिफर्म विन्डोहरू अन गर्नुहोस्"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"डेस्कटप ब्याकअप पासवर्ड"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"हाल डेस्कटपका सबै ब्याकअप पासवर्ड सुरक्षित छैनन्"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"डेस्कटप पूर्ण ब्याकअपको लागि पासवर्ड बदल्न वा हटाउन ट्याप गर्नुहोस्"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"पूरा चार्ज हुन <xliff:g id="TIME">%1$s</xliff:g> लाग्ने छ"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - पूरा चार्ज हुन <xliff:g id="TIME">%2$s</xliff:g> लाग्ने छ"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्ज गर्ने प्रक्रिया अप्टिमाइज गरिएको छ"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्ज गरिँदै छ"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> बजेसम्ममा पूरा चार्ज हुने छ"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> बजेसम्ममा पूरा चार्ज हुने छ"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 8577f48..abf00f0 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Hiermee komt elke app in aanmerking voor schrijven naar externe opslag, ongeacht de manifestwaarden"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Formaat activiteiten geforceerd aanpasbaar maken"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Maak het formaat van alle activiteiten aanpasbaar, ongeacht de manifestwaarden"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Vensters met vrije vorm aanzetten (verouderd)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Zet ondersteuning voor verouderde vensters met experimentele vrije vorm aan."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Vensters met vrije vorm aanzetten"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Wachtwoord desktopback-up"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Volledige back-ups naar desktops zijn momenteel niet beveiligd"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tik om het wachtwoord voor volledige back-ups naar desktops te wijzigen of te verwijderen"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Vol over <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - vol over <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Opladen geoptimaliseerd"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Opladen"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Vol om <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Volledig opgeladen om <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 9fdb99b..941a627 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"ଯେକୌଣସି ଆପ୍କୁ ଏକ୍ସଟର୍ନଲ୍ ଷ୍ଟୋରେଜ୍ରେ ଲେଖାଯୋଗ୍ୟ କରନ୍ତୁ, ମେନିଫେଷ୍ଟ ମୂଲ୍ୟ ଯାହା ହୋଇଥାଉ ନା କାହିଁକି"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"ୱିଣ୍ଡୋ ହିସାବରେ କାର୍ଯ୍ୟକଳାପର ଆକାର ବଦଳାନ୍ତୁ"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"ମାନିଫେଷ୍ଟ ମୂଲ୍ୟ ଯାହା ହୋଇଥାଉ ନା କାହିଁକି, ଏକାଧିକ-ୱିଣ୍ଡୋ ପାଇଁ ସମସ୍ତ କାର୍ଯ୍ୟକଳାପକୁ ରିସାଇଜ କରନ୍ତୁ।"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"ଫ୍ରିଫର୍ମ ୱିଣ୍ଡୋ ସକ୍ଷମ କରନ୍ତୁ (ଲିଗାସି)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"ପରୀକ୍ଷାମୂଳକ ଲିଗାସି ଫ୍ରିଫର୍ମ ୱିଣ୍ଡୋ ପାଇଁ ସପୋର୍ଟ ସକ୍ଷମ କରନ୍ତୁ।"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"ଫ୍ରିଫର୍ମ ୱିଣ୍ଡୋକୁ ସକ୍ଷମ କରନ୍ତୁ"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ଡେସ୍କଟପ ବେକଅପ ପାସୱାର୍ଡ"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ଡେସ୍କଟପ୍ର ସମ୍ପୂର୍ଣ୍ଣ ବ୍ୟାକଅପ୍ଗୁଡ଼ିକ ବର୍ତ୍ତମାନ ସୁରକ୍ଷିତ ନୁହେଁ"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ଡେସ୍କଟପ୍ର ସମ୍ପୂର୍ଣ୍ଣ ବ୍ୟାକ୍ଅପ୍ ପାଇଁ ପାସ୍ୱର୍ଡ ବଦଳାଇବା କିମ୍ୱା କାଢ଼ିଦେବା ନିମନ୍ତେ ଟାପ୍ କରନ୍ତୁ"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"ପୂର୍ଣ୍ଣ ହେବାକୁ ଆଉ <xliff:g id="TIME">%1$s</xliff:g> ବାକି ଅଛି"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - ପୂର୍ଣ୍ଣ ହେବାକୁ ଆଉ <xliff:g id="TIME">%2$s</xliff:g> ବାକି ଅଛି"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ଚାର୍ଜିଂକୁ ଅପ୍ଟିମାଇଜ କରାଯାଇଛି"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ ଚାର୍ଜିଂ"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> ସୁଦ୍ଧା ସମ୍ପୂର୍ଣ୍ଣ ଚାର୍ଜ ହେବ"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> • <xliff:g id="TIME">%2$s</xliff:g> ସୁଦ୍ଧା ସମ୍ପୂର୍ଣ୍ଣ ଭାବେ ଚାର୍ଜ ହୋଇଯିବ"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 64981a7..09fd778 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"ਮੈਨੀਫੈਸਟ ਮੁੱਲਾਂ ਦੀ ਪਰਵਾਹ ਕੀਤੇ ਬਿਨਾਂ, ਕਿਸੇ ਵੀ ਐਪ ਨੂੰ ਬਾਹਰੀ ਸਟੋਰੇਜ \'ਤੇ ਲਿਖਣ ਦੇ ਯੋਗ ਬਣਾਉਂਦੀ ਹੈ"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"ਸਰਗਰਮੀਆਂ ਨੂੰ ਜ਼ਬਰਦਸਤੀ ਆਕਾਰ ਬਦਲਣਯੋਗ ਬਣਾਓ"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"ਮੈਨੀਫ਼ੈਸਟ ਮੁੱਲਾਂ ਦੀ ਪਰਵਾਹ ਕੀਤੇ ਬਿਨਾਂ, ਮਲਟੀ-ਵਿੰਡੋ ਲਈ ਸਾਰੀਆਂ ਸਰਗਰਮੀਆਂ ਨੂੰ ਆਕਾਰ ਬਦਲਣਯੋਗ ਬਣਾਓ।"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"ਫ੍ਰੀਫਾਰਮ ਵਿੰਡੋਆਂ ਚਾਲੂ ਕਰੋ (ਵਿਰਾਸਤੀ)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"ਪ੍ਰਯੋਗਮਈ ਵਿਰਾਸਤੀ ਫ੍ਰੀਫਾਰਮ ਵਿੰਡੋਆਂ ਲਈ ਸਹਾਇਤਾ ਚਾਲੂ ਕਰੋ।"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"ਫ੍ਰੀਫਾਰਮ ਵਿੰਡੋਜ਼ ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ਡੈਸਕਟਾਪ ਬੈਕਅੱਪ ਪਾਸਵਰਡ"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ਡੈਸਕਟਾਪ ਦੇ ਪੂਰੇ ਬੈਕਅੱਪ ਇਸ ਵੇਲੇ ਸੁਰੱਖਿਅਤ ਨਹੀਂ ਹਨ"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ਡੈਸਕਟਾਪ ਦੇ ਮੁਕੰਮਲ ਬੈਕਅੱਪਾਂ ਲਈ ਪਾਸਵਰਡ ਨੂੰ ਬਦਲਣ ਜਾਂ ਹਟਾਉਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"ਬੈਟਰੀ ਪੂਰੀ ਚਾਰਜ ਹੋਣ ਵਿੱਚ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਬੈਟਰੀ ਪੂਰੀ ਚਾਰਜ ਹੋਣ ਵਿੱਚ <xliff:g id="TIME">%2$s</xliff:g> ਬਾਕੀ"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਚਾਰਜਿੰਗ ਨੂੰ ਸੁਯੋਗ ਬਣਾਇਆ ਗਿਆ"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> ਤੱਕ ਪੂਰੀ ਤਰ੍ਹਾਂ ਚਾਰਜ ਹੋ ਜਾਵੇਗੀ"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ਤੱਕ ਪੂਰੀ ਤਰ੍ਹਾਂ ਚਾਰਜ ਹੋ ਜਾਵੇਗੀ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index a1ca4a6..7840cb0 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Pozwala na zapis aplikacji w pamięci zewnętrznej niezależnie od wartości w pliku manifestu"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Wymuś zmianę rozmiaru okien aktywności"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Zezwalaj na zmianę rozmiaru wszystkich okien aktywności w trybie wielu okien niezależnie od ustawień w pliku manifestu"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Włącz dowolny rozmiar okien (starsza wersja)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Włącz obsługę eksperymentalnej funkcji dowolnego rozmiaru okien w starszej wersji"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Włącz dowolny rozmiar okien"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Hasło kopii zapasowej"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Pełne kopie zapasowe na komputerze nie są obecnie chronione"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Dotknij, by zmienić lub usunąć hasło pełnych kopii zapasowych na komputerze."</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do pełnego naładowania"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – ładowanie zoptymalizowane"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – ładowanie"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Bateria będzie pełna do <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Pełne naładowanie do <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 13f9c40..9209d62 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Qualificar apps para gravação em armazenamento externo, independentemente dos valores do manifesto"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Forçar atividades a serem redimensionáveis"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Ativar janelas de forma livre (legado)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Ativar a compatibilidade com janelas experimentais legadas de forma livre."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Ativar janelas de forma livre"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Senha de backup local"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Os backups completos não estão protegidos no momento"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Toque para alterar ou remover a senha de backups completos do desktop"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> até a conclusão"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a conclusão"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carregamento otimizado"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> (carregando)"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Carregado até <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Totalmente carregado até <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 260e58e..2cd6811 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Torna qualquer aplicação elegível para ser gravada no armazenamento externo, independentemente dos valores do manifesto"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Forçar as atividades a serem redimensionáveis"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Ativar janelas de forma livre (antigo)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Ativar compatibilidade com janelas de forma livre antigas experimentais."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Ativar janelas de forma livre"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Palavra-passe cópia do computador"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"As cópias de segurança completas no ambiente de trabalho não estão atualmente protegidas"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tocar para alterar ou remover a palavra-passe para cópias de segurança completas no ambiente de trabalho"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> até à carga máxima"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até à carga máxima"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g>: carregamento otimizado"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – A carregar"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Completo à(s) <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Completamente carregado à(s) <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 13f9c40..9209d62 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Qualificar apps para gravação em armazenamento externo, independentemente dos valores do manifesto"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Forçar atividades a serem redimensionáveis"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Ativar janelas de forma livre (legado)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Ativar a compatibilidade com janelas experimentais legadas de forma livre."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Ativar janelas de forma livre"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Senha de backup local"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Os backups completos não estão protegidos no momento"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Toque para alterar ou remover a senha de backups completos do desktop"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> até a conclusão"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a conclusão"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carregamento otimizado"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> (carregando)"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Carregado até <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Totalmente carregado até <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 5f8f367..e33c02f 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Permite scrierea oricărei aplicații eligibile în stocarea externă, indiferent de valorile manifestului"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Forțează redimensionarea activităților"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permite redimensionarea tuturor activităților pentru modul cu ferestre multiple, indiferent de valorile manifestului."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Activează ferestrele cu formă liberă (vechi)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Activează compatibilitatea pentru ferestrele experimentale vechi cu formă liberă."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Activează ferestrele cu formă liberă"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Parolă backup computer"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"În prezent, backupurile complete pe computer nu sunt protejate"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Atinge ca să modifici sau să elimini parola pentru backupurile complete pe desktop"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> până la finalizare"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> până la finalizare"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Încărcare optimizată"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Se încarcă"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Timp rămas <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Complet încărcat în <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index f492b65..4de495a 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Разрешить сохранение приложений на внешних накопителях (независимо от значений в манифесте)"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Изменение размера в многооконном режиме"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Разрешить изменение размера окон в многооконном режиме (независимо от значений в манифесте)"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Разрешить окна произвольной формы (устаревшее)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Включить устаревшую экспериментальную функцию для создания окон произвольной формы"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Разрешить создание окон произвольной формы"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Пароль для резервного копирования"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Полные локальные резервные копии в настоящее время не защищены"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Нажмите, чтобы изменить или удалить пароль для резервного копирования"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до полной зарядки"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарядка оптимизирована"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – заряжается"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g>. <xliff:g id="STATUS">%2$s</xliff:g> – завершится к <xliff:g id="TIME">%3$s</xliff:g>."</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – полностью зарядится к <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 42cde8b..9a4ca8e 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"මැනිෆෙස්ට් අගයන් නොසලකා, ඕනෑම යෙදුමක් බාහිර ගබඩාවට ලිවීමට සුදුසුකම් ලබා දෙයි"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"ක්රියාකාරකම් ප්රතිප්රමාණ කළ හැකි බවට බල කරන්න"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"මැනිෆෙස්ට් අගයන් නොසලකා, සියලු ක්රියාකාරකම් බහු-කවුළුව සඳහා ප්රතිප්රමාණ කළ හැකි බවට පත් කරන්න."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"නිදහස් ආකෘති කවුළු සබල කරන්න (ලෙගසිය)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"පරීක්ෂණාත්මක ලෙගසි නිදහස් ආකෘති කවුළු සඳහා සහාය සබල කරන්න."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"අනියම් හැඩැති කවුළු සබල කරන්න"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ඩෙස්ක්ටොප් උපස්ථ මුරපදය"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ඩෙස්ක්ටොප් සම්පූර්ණ උපස්ථ දැනට ආරක්ෂා කර නොමැත"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ඩෙස්ක්ටොප් සම්පූර්ණ උපස්ථ සඳහා මුරපදය වෙනස් කිරීමට හෝ ඉවත් කිරීමට තට්ටු කරන්න"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"සම්පූර්ණ වීමට <xliff:g id="TIME">%1$s</xliff:g>ක් ඉතිරියි"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - සම්පූර්ණ වීමට <xliff:g id="TIME">%2$s</xliff:g>ක් ඉතිරියි"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආරෝපණය ප්රශස්ත කර ඇත"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආරෝපණය වේ"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> හට පෙර සම්පූර්ණයි"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> හට පෙර සම්පූර්ණයෙන් ආරෝපණ වෙයි"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 6bf0cdb..189e729 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Umožniť zapísať akúkoľvek aplikáciu do externého úložiska bez ohľadu na hodnoty v manifeste"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Vynútiť možnosť zmeny veľkosti aktivít"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Umožniť zmeniť veľkosť všetkých aktivít na niekoľko okien (bez ohľadu na hodnoty manifestu)"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Povolenie meniteľných okien (starých)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Povoľte podporu pre experimentálne staré meniteľné okná."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Povoliť okná s voľným tvarom"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Heslo pre zálohy v počítači"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Úplné zálohy v počítači nie sú momentálne chránené"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Klepnutím zmeníte alebo odstránite heslo pre úplné zálohy do počítača"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do úplného nabitia"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Nabíjanie je optimalizované"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – nabíja sa"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – čas do nabitia: <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – čas do úplného nabitia: <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 869958f..a7367ad 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsako aplikacijo zapisati v zunanjo shrambo."</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Vsili spremembo velikosti za aktivnosti"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsem aktivnostim spremeniti velikost za način z več okni."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Omogoči okna svobodne oblike (starejše)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Omogoči podporo za poskusna okna svobodne oblike starejše različice."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Omogoči okna svobodne oblike"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Geslo za varnostno kopijo namizja"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Popolne varnostne kopije namizja trenutno niso zaščitene."</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Dotaknite se, če želite spremeniti ali odstraniti geslo za popolno varnostno kopiranje namizja"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Še <xliff:g id="TIME">%1$s</xliff:g> do napolnjenosti"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – še <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – polnjenje je optimizirano"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – polnjenje"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – popolnoma napolnjena do <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – popolnoma napolnjena do <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 0c1bf6c..688a098 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Bën që çdo aplikacion të jetë i përshtatshëm për t\'u shkruar në hapësirën ruajtëse të jashtme, pavarësisht nga vlerat e manifestit"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Detyro madhësinë e ndryshueshme për aktivitetet"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Bëj që të gjitha aktivitetet të kenë madhësi të ndryshueshme për përdorimin me shumë dritare, pavarësisht vlerave të manifestit."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Aktivizo dritaret me formë të lirë (të vjetra)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Aktivizo mbështetjen për dritaret eksperimentale me formë të lirë të versionit të vjetër."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Aktivizo dritaret me formë të lirë"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Fjalëkalimi i rezervimit të desktopit"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Rezervimet e plota të desktopit nuk janë të mbrojtura aktualisht"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Trokit për të ndryshuar ose hequr fjalëkalimin për rezervime të plota të desktopit"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> derisa të mbushet"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> derisa të mbushet"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Karikimi u optimizua"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Po karikohet"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Plot deri në <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Karikohet plotësisht deri në <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 2b004cb..17f5c2a 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Омогућава уписивање свих апликација у спољну меморију, без обзира на вредности манифеста"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Принудно омогући промену величине активности"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Омогућава промену величине свих активности за режим са више прозора, без обзира на вредности манифеста."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Омогући прозоре произвољног формата (застарело)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Омогућава подршку за застареле експерименталне прозоре произвољног формата."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Омогући прозоре произвољног формата"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Лозинка резервне копије за рачунар"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Резервне копије читавог система тренутно нису заштићене"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Додирните да бисте променили или уклонили лозинку за прављење резервних копија читавог система на рачунару"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до краја пуњења"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до краја пуњења"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – пуњење је оптимизовано"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Пуњење"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Потпуно напуњено до <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Потпуно напуњено до <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 06ed90e..c50d3c3 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Allar appar kan skrivas till extern lagring, oavsett manifestvärden"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Framtvinga storleksanpassning för aktiviteter"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Gör det möjligt att ändra storleken på alla aktiviteter i flerfönsterläge, oavsett manifestvärden."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Aktivera frihandsfönster (äldre)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Aktivera stöd för äldre experimentella frihandsfönster."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Aktivera frihandsfönster"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Lösenord för säkerhetskopia av datorn"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"De fullständiga säkerhetskopiorna av datorn är för närvarande inte skyddade"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tryck om du vill ändra eller ta bort lösenordet för fullständig säkerhetskopiering av datorn"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> kvar tills fulladdat"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kvar tills fulladdat"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Laddningen har optimerats"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – laddas"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – fulladdad till <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – fulladdad till <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 08aa784..0c71dd1 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Huruhusu programu yoyote iwekwe kwenye hifadhi ya nje, bila kujali thamani za faili ya maelezo"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Lazimisha shughuli ziweze kubadilishwa ukubwa"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Fanya shughuli zote ziweze kubadilishwa ukubwa kwenye madirisha mengi, bila kuzingatia thamani za faili ya maelezo."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Washa madirisha yenye muundo huru (yaliyopitwa na wakati)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Ruhusu matumizi ya madirisha ya majaribio yenye muundo huru yaliyopitwa na wakati."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Washa madirisha yenye muundo huru"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Nenosiri la hifadhi rudufu ya eneo kazi"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Hifadhi rudufu kamili za eneo kazi hazijalindwa kwa sasa"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Gusa ili ubadilishe au uondoe nenosiri la hifadhi rudufu kamili za eneo kazi"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Zimesalia <xliff:g id="TIME">%1$s</xliff:g> ijae chaji"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> zimesalia ijae chaji"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Hali ya kuchaji imeboreshwa"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Inachaji"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Itajaa kufikia <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Betri itajaa chaji kufikia <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 5972756..2908b63 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"மேனிஃபெஸ்ட் மதிப்புகளைப் பொருட்படுத்தாமல், எல்லா ஆப்ஸையும் வெளிப்புறச் சேமிப்பிடத்தில் எழுத அனுமதிக்கும்"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"செயல்பாடுகளை அளவுமாறக்கூடியதாக அமை"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"மேனிஃபெஸ்ட் மதிப்புகளைப் பொருட்படுத்தாமல், பல சாளரத்திற்கு எல்லா செயல்பாடுகளையும் அளவுமாறக்கூடியதாக அமை."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"குறிப்பிட்ட வடிவமில்லாத சாளரத்தை இயக்குதல் (லெகஸி)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"பரிசோதனைக்குரிய, குறிப்பிட்ட வடிவமில்லாத பழைய சாளரங்களுக்கான ஆதரவை இயக்குதல்."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"குறிப்பிட்ட வடிவமில்லாத சாளரங்களை இயக்கு"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"டெஸ்க்டாப் காப்புப்பிரதி கடவுச்சொல்"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"டெஸ்க்டாப்பின் முழு காப்புப்பிரதிகள் தற்போது பாதுகாக்கப்படவில்லை"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"டெஸ்க்டாப்பின் முழுக் காப்புப் பிரதிகளுக்கான கடவுச்சொல்லை மாற்ற அல்லது அகற்ற, தட்டவும்"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"முழுவதும் சார்ஜாக <xliff:g id="TIME">%1$s</xliff:g> ஆகும்"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - முழுவதும் சார்ஜாக <xliff:g id="TIME">%2$s</xliff:g> ஆகும்"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - சார்ஜிங் மேம்படுத்தப்பட்டது"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ சார்ஜாகிறது"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>க்கு முழுமையாகச் சார்ஜாகிவிடும்"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>க்கு முழுமையாகச் சார்ஜாகிவிடும்"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 1df1823..c188bdb 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"ఏ యాప్ను అయినా మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా బాహ్య స్టోరేజ్లో సేవ్ చేయడానికి అనుమతిస్తుంది"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"యాక్టివిటీ విండోల సైజ్ మార్చగలిగేలా నిర్బంధించు"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా అన్ని యాక్టివిటీస్ను పలు రకాల విండోల్లో సరిపోయేటట్లు సైజ్ మార్చగలిగేలా చేస్తుంది."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"ఫ్రీఫార్మ్ విండోలను ఎనేబుల్ చేయండి (లెగసీ)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"ప్రయోగాత్మక లెగసీ ఫ్రీఫార్మ్ విండోలకు సంబంధించిన సపోర్ట్ను ఎనేబుల్ చేయండి."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"స్వతంత్ర రూప విండోలను ఎనేబుల్ చేయండి"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"డెస్క్టాప్ బ్యాకప్ పాస్వర్డ్"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"డెస్క్టాప్ పూర్తి బ్యాకప్లు ప్రస్తుతం రక్షించబడలేదు"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"డెస్క్టాప్ పూర్తి బ్యాకప్ల కోసం పాస్వర్డ్ను మార్చడానికి లేదా తీసివేయడానికి నొక్కండి"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ఛార్జింగ్ ఆప్టిమైజ్ చేయబడింది"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ఛార్జ్ అవుతోంది"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>కు పూర్తవుతుంది"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>కు పూర్తిగా ఛార్జ్ అవుతుంది"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index c26f02d..b9510a8 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"ทำให้เขียนแอปในที่จัดเก็บข้อมูลภายนอกได้ โดยไม่คำนึงถึงค่าในไฟล์ Manifest"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"บังคับให้กิจกรรมปรับขนาดได้"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"ทำให้กิจกรรมทั้งหมดปรับขนาดได้สำหรับหน้าต่างหลายบาน โดยไม่คำนึงถึงค่าในไฟล์ Manifest"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"เปิดใช้หน้าต่างรูปแบบอิสระ (แบบเดิม)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"เปิดใช้การรองรับหน้าต่างรูปแบบอิสระแบบเดิมเวอร์ชันทดลอง"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"เปิดใช้หน้าต่างรูปแบบอิสระ"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"รหัสผ่านการสำรองข้อมูลในเดสก์ท็อป"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"การสำรองข้อมูลเต็มรูปแบบในเดสก์ท็อปไม่ได้รับการป้องกันในขณะนี้"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"แตะเพื่อเปลี่ยนแปลงหรือลบรหัสผ่านสำหรับการสำรองข้อมูลเต็มรูปแบบในเดสก์ท็อป"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"อีก <xliff:g id="TIME">%1$s</xliff:g>จึงจะเต็ม"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - อีก <xliff:g id="TIME">%2$s</xliff:g> จึงจะเต็ม"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ปรับการชาร์จให้เหมาะสมแล้ว"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ กำลังชาร์จ"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - จะเต็มภายใน <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - จะชาร์จเต็มภายใน <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 1c038f6..32cc961 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Ginagawang kwalipikado ang anumang app na mailagay sa external na storage, anuman ang mga value ng manifest"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Sapilitang gawing resizable ang mga aktibidad"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Gawing nare-resize ang lahat ng aktibidad para sa multi-window, anuman ang mga value ng manifest."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"I-enable ang mga freeform window (legacy)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"I-enable ang suporta para sa mga pang-eksperimentong legacy na freeform window."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"I-enable ang mga freeform window"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Password ng pag-backup ng desktop"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Kasalukuyang hindi pinoprotektahan ang mga buong pag-backup ng desktop"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"I-tap upang baguhin o alisin ang password para sa mga kumpletong pag-back up sa desktop"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> na lang bago mapuno"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> na lang bago mapuno"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Naka-optimize ang pag-charge"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Nagcha-charge"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Mapupuno sa <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Mafu-full charge sa <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 79ace3f..6bfc1ee 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Manifest değerlerinden bağımsız olarak uygulamaları harici depolamaya yazmak için uygun hale getirir"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Etkinlikleri yeniden boyutlandırılabilmeye zorla"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Manifest değerlerinden bağımsız olarak, tüm etkinlikleri birden fazla pencerede yeniden boyutlandırılabilir yap."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Serbest biçimli pencereleri (eski) etkinleştir"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Deneysel eski serbest biçimli pencere desteğini etkinleştir."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Serbest biçimli pencereleri etkinleştir"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Masaüstü yedekleme şifresi"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Masaüstü tam yedeklemeleri şu an korunmuyor"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Masaüstü tam yedeklemelerinin şifresini değiştirmek veya kaldırmak için dokunun"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Tamamen şarj olmasına <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tamamen şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Şarj işlemi optimize edildi"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Şarj ediliyor"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Tamamen dolacağı zaman: <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tamamen şarj olacağı zaman: <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index de416d2..083a130 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Можна записувати додатки в зовнішню пам’ять, незалежно від значень у маніфесті"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Примусово масштабувати активність"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Масштабувати активність на кілька вікон, незалежно від значень у файлі маніфесту."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Увімкнути старий формат вікон змінного розміру"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Увімкнути підтримку експериментального старого формату вікон змінного розміру."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Увімкнути вікна довільного формату"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Пароль рез. копії на ПК"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Повні резервні копії на комп’ютері наразі не захищені"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Торкніться, щоб змінити або видалити пароль для повного резервного копіювання на комп’ютер"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до повного заряду"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного заряду"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – заряджання оптимізовано"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – заряджається"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Завершиться до <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Повністю зарядиться до <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 3092832..6508d51 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"manifest اقدار سے قطع نظر، کسی بھی ایپ کو بیرونی اسٹوریج پر لکھے جانے کا اہل بناتا ہے"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"سرگرمیوں کو ری سائز ایبل بنائیں"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"مینی فیسٹ اقدار سے قطع نظر، ملٹی ونڈو کیلئے تمام سرگرمیوں کو ری سائز ایبل بنائیں۔"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"فریفارم ونڈوز کو فعال کریں (legacy)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"تجرباتی legacy فری فارم ونڈوز کیلئے سپورٹ فعال کریں۔"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"freeform ونڈوز فعال کریں"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ڈیسک ٹاپ کا بیک اپ پاس ورڈ"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ڈیسک ٹاپ کے مکمل بیک اپس فی الحال محفوظ کیے ہوئے نہیں ہیں"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ڈیسک ٹاپ کے مکمل بیک اپس کیلئے پاس ورڈ کو تبدیل کرنے یا ہٹانے کیلئے تھپتھپائیں"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"مکمل چارج ہونے میں <xliff:g id="TIME">%1$s</xliff:g> باقی ہے"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"مکمل چارج ہونے میں <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> باقی ہے"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - چارجنگ کو بہتر بنایا گیا"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - چارج ہو رہی ہے"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> تک مکمل ہو جائے گی"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تک مکمل چارج ہو جائے گی"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 7502412..738c815 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Manifest qiymatidan qat’i nazar istalgan ilovani tashqi xotiraga saqlash imkonini beradi"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Harakatlarni moslashuvchan o‘lchamga keltirish"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Manifest qiymatidan qat’i nazar barcha harakatlarni ko‘p oynali rejimga moslashtirish."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Erkin shakldagi oynalarni (eskirgan) yoqish"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Eskirgan erkin shakldagi oynalar yaratish uchun moʻljallangan tajribaviy funksiyani yoqish."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Erkin shakldagi oynalarni yoqish"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Zaxira nusxa uchun parol"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Kompyuterdagi zaxira nusxalar hozirgi vaqtda himoyalanmagan"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Ish stoli to‘liq zaxira nusxalari parolini o‘zgartirish yoki o‘chirish uchun bu yerni bosing"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Toʻlishiga <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – Toʻlishiga <xliff:g id="TIME">%2$s</xliff:g> qoldi"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Quvvatlash optimallashtirildi"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Quvvatlanmoqda"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Toʻladi: <xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Toʻliq quvvatlanadi: <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 02f0aa1..38b4e4f 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Cho phép ghi mọi ứng dụng đủ điều kiện vào bộ nhớ ngoài, bất kể giá trị tệp kê khai là gì"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Buộc các hoạt động có thể thay đổi kích thước"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Cho phép thay đổi kích thước của tất cả các hoạt động cho nhiều cửa sổ, bất kể giá trị tệp kê khai là gì."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Bật cửa sổ có thể đổi kích thước (cũ)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Bật tính năng hỗ trợ cửa sổ có thể đổi kích thước thử nghiệm (cũ)."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Bật cửa sổ dạng tự do"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Mật khẩu cho bản sao lưu qua máy tính"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Các bản sao lưu đầy đủ qua máy tính hiện không được bảo vệ"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Nhấn để thay đổi hoặc xóa mật khẩu dành cho các bản sao lưu đầy đủ vào máy tính"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> nữa là pin đầy"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> nữa là pin đầy"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Quá trình sạc được tối ưu hoá"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Đang sạc"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Đến <xliff:g id="TIME">%3$s</xliff:g> pin sẽ đầy"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Đến <xliff:g id="TIME">%2$s</xliff:g> pin sẽ đầy"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index a551121..21cd458 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"允许将任何应用写入外部存储设备(无论清单值是什么)"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"强制将 activity 设为可调整大小"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"将所有 activity 设为可配合多窗口环境调整大小(无论清单值是什么)。"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"启用可自由调整的窗口(旧版)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"实现对实验性旧版可自由调整的窗口的支持。"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"启用可自由调整的窗口"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"桌面备份密码"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"桌面完整备份当前未设置密码保护"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"点按即可更改或移除用于保护桌面完整备份的密码"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"还需<xliff:g id="TIME">%1$s</xliff:g>充满"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充电方式已优化"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - 正在充电"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> 前充满"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 前充满"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 6f8c537..8ad35e6 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"在任何資訊清單值下,允許將所有符合資格的應用程式寫入到外部儲存完間"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"強制將活動設為可調整尺寸"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"在任何資訊清單值下,允許系統配合多重視窗環境調整所有活動的尺寸。"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"啟用自由形態視窗 (舊的)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"啟用舊的實驗版自由形態視窗的支援功能。"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"啟用自由形態視窗"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"桌面電腦備份密碼"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"桌面電腦的完整備份目前未受保護"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"輕按即可變更或移除桌面電腦完整備份的密碼"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g>後充滿電"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充滿電"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - 已優化充電"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ 充電中"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - 在 <xliff:g id="TIME">%3$s</xliff:g>前充滿電"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> • 在 <xliff:g id="TIME">%2$s</xliff:g>前充滿電"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 2806b02..8265bba 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"允許將任何應用程式寫入外部儲存空間 (無論資訊清單值為何)"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"將活動強制設為可調整大小"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"將所有活動設為可配合多重視窗環境調整大小 (無論資訊清單值為何)。"</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"啟用自由形式視窗 (舊版)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"啟用實驗性舊版自由形式視窗支援功能。"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"啟用自由形式視窗"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"電腦備份密碼"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"尚未設定密碼保護電腦的完整備份"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"輕觸即可變更或移除電腦完整備份的密碼"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g>後充飽"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電效能已最佳化"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電中"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> 前充飽"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 前充飽"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 570c424..b2f46b5 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -430,8 +430,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Yenza noma uluphi uhlelo lokusebenza lifaneleke ukuthi libhalwe kusitoreji sangaphandle, ngaphandle kwamavelu we-manifest"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Imisebenzi yamandla izonikezwa usayizi omusha"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Yenza yonke imisebenzi ibe nosayizi abasha kumawindi amaningi, ngokunganaki amavelu e-manifest."</string>
- <string name="enable_freeform_support" msgid="8409932201445109106">"Vumela amawindi efreeform (ifa)"</string>
- <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Nika amandla amawindi efreeform efa elisahlolwa."</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Nika amandla amawindi e-freeform"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Iphasiwedi yokusekela ngokulondoloza ye-Desktop"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Ukusekela ngokulondoloza okugcwele kwe-Desktop akuvikelekile okwamanje."</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Thepha ukushintsha noma ukususa iphasiwedi yokwenziwa kwezipele ngokugcwele kwideskithophu"</string>
@@ -496,7 +495,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> okusele kuze kugcwale"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> okusele kuze kugcwale"</string>
- <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ukushaja kuthuthukisiwe"</string>
+ <!-- no translation found for power_charging_limited (4144004473976005214) -->
+ <skip />
<string name="power_charging_future_paused" msgid="1809543660923642799">"Iku-<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Iyashaja"</string>
<string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Igcwala ngo-<xliff:g id="TIME">%3$s</xliff:g>"</string>
<string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> • Ishajwe ngokugcwele ngo-<xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 5c4cdb2..687c728 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -881,6 +881,11 @@
<!-- UI debug setting: show physical key presses summary [CHAR LIMIT=150] -->
<string name="show_key_presses_summary">Show visual feedback for physical key presses</string>
+ <!-- UI debug setting: Title text for a debug setting that enables a visualization of touchpad input in a window on the screen [CHAR LIMIT=50] -->
+ <string name="touchpad_visualizer">Show touchpad input</string>
+ <!-- UI debug setting: Summary text for a debug setting that enables a visualization of touchpad input in a window on the screen [CHAR LIMIT=150] -->
+ <string name="touchpad_visualizer_summary">Screen overlay displaying touchpad input data and recognized gestures</string>
+
<!-- UI debug setting: show where surface updates happen? [CHAR LIMIT=25] -->
<string name="show_screen_updates">Show surface updates</string>
<!-- UI debug setting: show surface updates summary [CHAR LIMIT=50] -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index e926b16..0dc772a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -16,8 +16,6 @@
package com.android.settingslib.bluetooth;
-import static com.android.settingslib.flags.Flags.enableCachedBluetoothDeviceDedup;
-
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothCsipSetCoordinator;
@@ -403,7 +401,7 @@
cachedDevice = mDeviceManager.addDevice(device);
}
- if (enableCachedBluetoothDeviceDedup() && bondState == BluetoothDevice.BOND_BONDED) {
+ if (bondState == BluetoothDevice.BOND_BONDED) {
mDeviceManager.removeDuplicateInstanceForIdentityAddress(device);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index 0543177..de60fdc2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -578,7 +578,7 @@
}
/**
- * Check if {@link CachedBluetoothDevice} has connected to a broadcast source.
+ * Check if {@link CachedBluetoothDevice} (lead or member) has connected to a broadcast source.
*
* @param cachedDevice The cached bluetooth device to check.
* @param localBtManager The BT manager to provide BT functions.
@@ -586,20 +586,10 @@
*/
@WorkerThread
public static boolean hasConnectedBroadcastSource(
- CachedBluetoothDevice cachedDevice, LocalBluetoothManager localBtManager) {
- if (localBtManager == null) {
- Log.d(TAG, "Skip check hasConnectedBroadcastSource due to bt manager is null");
- return false;
- }
- LocalBluetoothLeBroadcastAssistant assistant =
- localBtManager.getProfileManager().getLeAudioBroadcastAssistantProfile();
- if (assistant == null) {
- Log.d(TAG, "Skip check hasConnectedBroadcastSource due to assistant profile is null");
- return false;
- }
- List<BluetoothLeBroadcastReceiveState> sourceList =
- assistant.getAllSources(cachedDevice.getDevice());
- if (!sourceList.isEmpty() && sourceList.stream().anyMatch(BluetoothUtils::isConnected)) {
+ @Nullable CachedBluetoothDevice cachedDevice,
+ @Nullable LocalBluetoothManager localBtManager) {
+ if (cachedDevice == null) return false;
+ if (hasConnectedBroadcastSourceForBtDevice(cachedDevice.getDevice(), localBtManager)) {
Log.d(
TAG,
"Lead device has connected broadcast source, device = "
@@ -608,9 +598,7 @@
}
// Return true if member device is in broadcast.
for (CachedBluetoothDevice device : cachedDevice.getMemberDevice()) {
- List<BluetoothLeBroadcastReceiveState> list =
- assistant.getAllSources(device.getDevice());
- if (!list.isEmpty() && list.stream().anyMatch(BluetoothUtils::isConnected)) {
+ if (hasConnectedBroadcastSourceForBtDevice(device.getDevice(), localBtManager)) {
Log.d(
TAG,
"Member device has connected broadcast source, device = "
@@ -621,6 +609,28 @@
return false;
}
+ /**
+ * Check if {@link BluetoothDevice} has connected to a broadcast source.
+ *
+ * @param device The bluetooth device to check.
+ * @param localBtManager The BT manager to provide BT functions.
+ * @return Whether the device has connected to a broadcast source.
+ */
+ @WorkerThread
+ public static boolean hasConnectedBroadcastSourceForBtDevice(
+ @Nullable BluetoothDevice device, @Nullable LocalBluetoothManager localBtManager) {
+ LocalBluetoothLeBroadcastAssistant assistant =
+ localBtManager == null
+ ? null
+ : localBtManager.getProfileManager().getLeAudioBroadcastAssistantProfile();
+ if (device == null || assistant == null) {
+ Log.d(TAG, "Skip check hasConnectedBroadcastSourceForBtDevice due to arg is null");
+ return false;
+ }
+ List<BluetoothLeBroadcastReceiveState> sourceList = assistant.getAllSources(device);
+ return !sourceList.isEmpty() && sourceList.stream().anyMatch(BluetoothUtils::isConnected);
+ }
+
/** Checks the connectivity status based on the provided broadcast receive state. */
@WorkerThread
public static boolean isConnected(BluetoothLeBroadcastReceiveState state) {
@@ -805,8 +815,10 @@
ComponentName exclusiveManagerComponent =
ComponentName.unflattenFromString(exclusiveManagerName);
- String exclusiveManagerPackage = exclusiveManagerComponent != null
- ? exclusiveManagerComponent.getPackageName() : exclusiveManagerName;
+ String exclusiveManagerPackage =
+ exclusiveManagerComponent != null
+ ? exclusiveManagerComponent.getPackageName()
+ : exclusiveManagerName;
if (!isPackageInstalledAndEnabled(context, exclusiveManagerPackage)) {
return false;
@@ -864,7 +876,7 @@
if (localBtManager == null) return null;
LocalBluetoothLeBroadcast broadcast =
localBtManager.getProfileManager().getLeAudioBroadcastProfile();
- if (!broadcast.isEnabled(null)) return null;
+ if (broadcast == null || !broadcast.isEnabled(null)) return null;
int primaryGroupId = getPrimaryGroupIdForBroadcast(contentResolver);
if (primaryGroupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) return null;
LocalBluetoothLeBroadcastAssistant assistant =
@@ -883,4 +895,4 @@
}
return null;
}
-}
\ No newline at end of file
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index cb6a930..8b6351e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -40,7 +40,7 @@
private static final String TAG = "CachedBluetoothDeviceManager";
private static final boolean DEBUG = BluetoothUtils.D;
- @VisibleForTesting static int sLateBondingTimeoutMillis = 5000; // 5s
+ @VisibleForTesting static int sLateBondingTimeoutMillis = 10000; // 10s
private Context mContext;
private final LocalBluetoothManager mBtManager;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingModel.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingModel.kt
new file mode 100644
index 0000000..db78280
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingModel.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth.devicesettings.shared.model
+
+import android.content.Intent
+import android.graphics.Bitmap
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.settingslib.bluetooth.devicesettings.DeviceSettingId
+
+/** Models a device setting. */
+sealed interface DeviceSettingModel {
+ val cachedDevice: CachedBluetoothDevice
+ @DeviceSettingId val id: Int
+
+ /** Models a device setting which should be displayed as an action/switch preference. */
+ data class ActionSwitchPreference(
+ override val cachedDevice: CachedBluetoothDevice,
+ @DeviceSettingId override val id: Int,
+ val title: String,
+ val summary: String? = null,
+ val icon: Bitmap? = null,
+ val intent: Intent? = null,
+ val switchState: DeviceSettingStateModel.ActionSwitchPreferenceState? = null,
+ val isAllowedChangingState: Boolean = true,
+ val updateState: ((DeviceSettingStateModel.ActionSwitchPreferenceState) -> Unit)? = null,
+ ) : DeviceSettingModel
+
+ /** Models a device setting which should be displayed as a multi-toggle preference. */
+ data class MultiTogglePreference(
+ override val cachedDevice: CachedBluetoothDevice,
+ @DeviceSettingId override val id: Int,
+ val title: String,
+ val toggles: List<ToggleModel>,
+ val isActive: Boolean,
+ val state: DeviceSettingStateModel.MultiTogglePreferenceState,
+ val isAllowedChangingState: Boolean,
+ val updateState: (DeviceSettingStateModel.MultiTogglePreferenceState) -> Unit
+ ) : DeviceSettingModel
+
+ /** Models an unknown preference. */
+ data class Unknown(
+ override val cachedDevice: CachedBluetoothDevice,
+ @DeviceSettingId override val id: Int
+ ) : DeviceSettingModel
+}
+
+/** Models a toggle in [DeviceSettingModel.MultiTogglePreference]. */
+data class ToggleModel(val label: String, val icon: Bitmap)
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingStateModel.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingStateModel.kt
new file mode 100644
index 0000000..b404bb9
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingStateModel.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth.devicesettings.shared.model
+
+import com.android.settingslib.bluetooth.devicesettings.DeviceSettingPreferenceState
+
+/** Models a device setting state. */
+sealed interface DeviceSettingStateModel {
+ fun toParcelable(): DeviceSettingPreferenceState
+
+ /** Models a device setting state for action/switch preference. */
+ data class ActionSwitchPreferenceState(val checked: Boolean) : DeviceSettingStateModel {
+ override fun toParcelable() =
+ com.android.settingslib.bluetooth.devicesettings.ActionSwitchPreferenceState.Builder()
+ .setChecked(checked)
+ .build()
+ }
+
+ /** Models a device setting state for multi-toggle preference. */
+ data class MultiTogglePreferenceState(val selectedIndex: Int) : DeviceSettingStateModel {
+ override fun toParcelable() =
+ com.android.settingslib.bluetooth.devicesettings.MultiTogglePreferenceState.Builder()
+ .setState(selectedIndex)
+ .build()
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt b/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt
index 87ab6b3..e5d79a1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt
@@ -40,6 +40,8 @@
override val modes: Flow<List<ZenMode>>
get() = mutableModesFlow.asStateFlow()
+ private val activeModesDurations = mutableMapOf<String, Duration?>()
+
init {
updateNotificationPolicy()
}
@@ -64,8 +66,22 @@
mutableModesFlow.value = mutableModesFlow.value.filter { it.id != id }
}
+ fun getMode(id: String): ZenMode? {
+ return mutableModesFlow.value.find { it.id == id }
+ }
+
override fun activateMode(zenMode: ZenMode, duration: Duration?) {
activateMode(zenMode.id)
+ activeModesDurations[zenMode.id] = duration
+ }
+
+ fun getModeActiveDuration(id: String): Duration? {
+ if (!activeModesDurations.containsKey(id)) {
+ throw IllegalArgumentException(
+ "mode $id not manually activated, you need to call activateMode"
+ )
+ }
+ return activeModesDurations[id]
}
override fun deactivateMode(zenMode: ZenMode) {
@@ -78,6 +94,7 @@
fun deactivateMode(id: String) {
updateModeActiveState(id = id, isActive = false)
+ activeModesDurations.remove(id)
}
// Update the active state while maintaining the mode's position in the list
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java
index d36e2fe..f533c95 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java
@@ -28,6 +28,7 @@
import android.util.Log;
import androidx.annotation.DrawableRes;
+import androidx.annotation.VisibleForTesting;
import com.android.settingslib.R;
@@ -61,6 +62,12 @@
return sInstance;
}
+ /** Replaces the singleton instance of {@link ZenModesBackend} by the provided one. */
+ @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+ public static void setInstance(@Nullable ZenModesBackend backend) {
+ sInstance = backend;
+ }
+
ZenModesBackend(Context context) {
mContext = context;
mNotificationManager = context.getSystemService(NotificationManager.class);
diff --git a/packages/SettingsLib/src/com/android/settingslib/satellite/SatelliteDialogUtils.kt b/packages/SettingsLib/src/com/android/settingslib/satellite/SatelliteDialogUtils.kt
index 2dc2650..4b6bcf9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/satellite/SatelliteDialogUtils.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/satellite/SatelliteDialogUtils.kt
@@ -126,25 +126,37 @@
}
suspendCancellableCoroutine {continuation ->
- satelliteManager?.requestIsEnabled(Default.asExecutor(),
- object : OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> {
- override fun onResult(result: Boolean) {
- Log.i(TAG, "Satellite modem enabled status: $result")
- continuation.resume(result)
- }
+ try {
+ satelliteManager?.requestIsEnabled(Default.asExecutor(),
+ object : OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> {
+ override fun onResult(result: Boolean) {
+ Log.i(TAG, "Satellite modem enabled status: $result")
+ continuation.resume(result)
+ }
- override fun onError(error: SatelliteManager.SatelliteException) {
- super.onError(error)
- Log.w(TAG, "Can't get satellite modem enabled status", error)
- continuation.resume(false)
- }
- })
+ override fun onError(error: SatelliteManager.SatelliteException) {
+ super.onError(error)
+ Log.w(TAG, "Can't get satellite modem enabled status", error)
+ continuation.resume(false)
+ }
+ })
+ } catch (e: IllegalStateException) {
+ Log.w(TAG, "IllegalStateException: $e")
+ continuation.resume(false)
+ }
}
}
private suspend fun requestIsSessionStarted(
context: Context
): Boolean = withContext(Default) {
+ val satelliteManager: SatelliteManager? =
+ context.getSystemService(SatelliteManager::class.java)
+ if (satelliteManager == null) {
+ Log.w(TAG, "SatelliteManager is null")
+ return@withContext false
+ }
+
getIsSessionStartedFlow(context).conflate().first()
}
@@ -173,10 +185,16 @@
trySend(isSessionStarted)
}
- val registerResult = satelliteManager.registerForModemStateChanged(
- Default.asExecutor(),
- callback
- )
+ var registerResult = SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN
+ try {
+ registerResult = satelliteManager.registerForModemStateChanged(
+ Default.asExecutor(),
+ callback
+ )
+ } catch (e: IllegalStateException) {
+ Log.w(TAG, "IllegalStateException: $e")
+ }
+
if (registerResult != SatelliteManager.SATELLITE_RESULT_SUCCESS) {
// If the registration failed (e.g., device doesn't support satellite),
@@ -186,7 +204,13 @@
trySend(false)
}
- awaitClose { satelliteManager.unregisterForModemStateChanged(callback) }
+ awaitClose {
+ try {
+ satelliteManager.unregisterForModemStateChanged(callback)
+ } catch (e: IllegalStateException) {
+ Log.w(TAG, "IllegalStateException: $e")
+ }
+ }
}.flowOn(Default)
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
index 370d568..4551f1e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
@@ -56,7 +56,10 @@
import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
@RunWith(RobolectricTestRunner.class)
public class BluetoothUtilsTest {
@@ -557,8 +560,14 @@
}
@Test
- public void testHasConnectedBroadcastSource_deviceConnectedToBroadcastSource() {
+ public void testHasConnectedBroadcastSource_leadDeviceConnectedToBroadcastSource() {
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
+ CachedBluetoothDevice memberCachedDevice = mock(CachedBluetoothDevice.class);
+ BluetoothDevice memberDevice = mock(BluetoothDevice.class);
+ when(memberCachedDevice.getDevice()).thenReturn(memberDevice);
+ Set<CachedBluetoothDevice> memberCachedDevices = new HashSet<>();
+ memberCachedDevices.add(memberCachedDevice);
+ when(mCachedBluetoothDevice.getMemberDevice()).thenReturn(memberCachedDevices);
List<Long> bisSyncState = new ArrayList<>();
bisSyncState.add(1L);
@@ -566,7 +575,8 @@
List<BluetoothLeBroadcastReceiveState> sourceList = new ArrayList<>();
sourceList.add(mLeBroadcastReceiveState);
- when(mAssistant.getAllSources(any())).thenReturn(sourceList);
+ when(mAssistant.getAllSources(mBluetoothDevice)).thenReturn(sourceList);
+ when(mAssistant.getAllSources(memberDevice)).thenReturn(Collections.emptyList());
assertThat(
BluetoothUtils.hasConnectedBroadcastSource(
@@ -575,6 +585,79 @@
}
@Test
+ public void testHasConnectedBroadcastSource_memberDeviceConnectedToBroadcastSource() {
+ when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
+ CachedBluetoothDevice memberCachedDevice = mock(CachedBluetoothDevice.class);
+ BluetoothDevice memberDevice = mock(BluetoothDevice.class);
+ when(memberCachedDevice.getDevice()).thenReturn(memberDevice);
+ Set<CachedBluetoothDevice> memberCachedDevices = new HashSet<>();
+ memberCachedDevices.add(memberCachedDevice);
+ when(mCachedBluetoothDevice.getMemberDevice()).thenReturn(memberCachedDevices);
+
+ List<Long> bisSyncState = new ArrayList<>();
+ bisSyncState.add(1L);
+ when(mLeBroadcastReceiveState.getBisSyncState()).thenReturn(bisSyncState);
+
+ List<BluetoothLeBroadcastReceiveState> sourceList = new ArrayList<>();
+ sourceList.add(mLeBroadcastReceiveState);
+ when(mAssistant.getAllSources(memberDevice)).thenReturn(sourceList);
+ when(mAssistant.getAllSources(mBluetoothDevice)).thenReturn(Collections.emptyList());
+
+ assertThat(
+ BluetoothUtils.hasConnectedBroadcastSource(
+ mCachedBluetoothDevice, mLocalBluetoothManager))
+ .isTrue();
+ }
+
+ @Test
+ public void testHasConnectedBroadcastSource_deviceNotConnectedToBroadcastSource() {
+ when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
+
+ List<Long> bisSyncState = new ArrayList<>();
+ when(mLeBroadcastReceiveState.getBisSyncState()).thenReturn(bisSyncState);
+
+ List<BluetoothLeBroadcastReceiveState> sourceList = new ArrayList<>();
+ sourceList.add(mLeBroadcastReceiveState);
+ when(mAssistant.getAllSources(mBluetoothDevice)).thenReturn(sourceList);
+
+ assertThat(
+ BluetoothUtils.hasConnectedBroadcastSource(
+ mCachedBluetoothDevice, mLocalBluetoothManager))
+ .isFalse();
+ }
+
+ @Test
+ public void testHasConnectedBroadcastSourceForBtDevice_deviceConnectedToBroadcastSource() {
+ List<Long> bisSyncState = new ArrayList<>();
+ bisSyncState.add(1L);
+ when(mLeBroadcastReceiveState.getBisSyncState()).thenReturn(bisSyncState);
+
+ List<BluetoothLeBroadcastReceiveState> sourceList = new ArrayList<>();
+ sourceList.add(mLeBroadcastReceiveState);
+ when(mAssistant.getAllSources(mBluetoothDevice)).thenReturn(sourceList);
+
+ assertThat(
+ BluetoothUtils.hasConnectedBroadcastSourceForBtDevice(
+ mBluetoothDevice, mLocalBluetoothManager))
+ .isTrue();
+ }
+
+ @Test
+ public void testHasConnectedBroadcastSourceForBtDevice_deviceNotConnectedToBroadcastSource() {
+ List<Long> bisSyncState = new ArrayList<>();
+ when(mLeBroadcastReceiveState.getBisSyncState()).thenReturn(bisSyncState);
+
+ List<BluetoothLeBroadcastReceiveState> sourceList = new ArrayList<>();
+ sourceList.add(mLeBroadcastReceiveState);
+ when(mAssistant.getAllSources(mBluetoothDevice)).thenReturn(sourceList);
+
+ assertThat(
+ BluetoothUtils.hasConnectedBroadcastSourceForBtDevice(
+ mBluetoothDevice, mLocalBluetoothManager))
+ .isFalse();
+ }
+
+ @Test
public void isAvailableHearingDevice_isConnectedHearingAid_returnTure() {
when(mCachedBluetoothDevice.isConnectedHearingAidDevice()).thenReturn(true);
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
@@ -604,9 +687,19 @@
}
@Test
- public void getSecondaryDeviceForBroadcast_errorState_returnNull() {
- assertThat(BluetoothUtils.getSecondaryDeviceForBroadcast(mContext.getContentResolver(),
- mLocalBluetoothManager))
+ public void getSecondaryDeviceForBroadcast_noBroadcast_returnNull() {
+ assertThat(
+ BluetoothUtils.getSecondaryDeviceForBroadcast(
+ mContext.getContentResolver(), mLocalBluetoothManager))
+ .isNull();
+ }
+
+ @Test
+ public void getSecondaryDeviceForBroadcast_nullProfile_returnNull() {
+ when(mProfileManager.getLeAudioBroadcastProfile()).thenReturn(null);
+ assertThat(
+ BluetoothUtils.getSecondaryDeviceForBroadcast(
+ mContext.getContentResolver(), mLocalBluetoothManager))
.isNull();
}
@@ -616,6 +709,7 @@
mContext.getContentResolver(),
BluetoothUtils.getPrimaryGroupIdUriForBroadcast(),
1);
+ when(mBroadcast.isEnabled(any())).thenReturn(true);
CachedBluetoothDeviceManager deviceManager = mock(CachedBluetoothDeviceManager.class);
when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(deviceManager);
when(deviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedBluetoothDevice);
@@ -625,8 +719,9 @@
when(mAssistant.getAllSources(mBluetoothDevice)).thenReturn(ImmutableList.of(state));
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mBluetoothDevice));
- assertThat(BluetoothUtils.getSecondaryDeviceForBroadcast(mContext.getContentResolver(),
- mLocalBluetoothManager))
+ assertThat(
+ BluetoothUtils.getSecondaryDeviceForBroadcast(
+ mContext.getContentResolver(), mLocalBluetoothManager))
.isNull();
}
@@ -636,6 +731,7 @@
mContext.getContentResolver(),
BluetoothUtils.getPrimaryGroupIdUriForBroadcast(),
1);
+ when(mBroadcast.isEnabled(any())).thenReturn(true);
CachedBluetoothDeviceManager deviceManager = mock(CachedBluetoothDeviceManager.class);
when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(deviceManager);
CachedBluetoothDevice cachedBluetoothDevice = mock(CachedBluetoothDevice.class);
@@ -655,8 +751,9 @@
when(mAssistant.getAllConnectedDevices())
.thenReturn(ImmutableList.of(mBluetoothDevice, bluetoothDevice));
- assertThat(BluetoothUtils.getSecondaryDeviceForBroadcast(mContext.getContentResolver(),
- mLocalBluetoothManager))
+ assertThat(
+ BluetoothUtils.getSecondaryDeviceForBroadcast(
+ mContext.getContentResolver(), mLocalBluetoothManager))
.isEqualTo(mCachedBluetoothDevice);
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/satellite/SatelliteDialogUtilsTest.kt b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/satellite/SatelliteDialogUtilsTest.kt
index 31d7130..2078b36 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/satellite/SatelliteDialogUtilsTest.kt
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/satellite/SatelliteDialogUtilsTest.kt
@@ -71,9 +71,7 @@
`when`(satelliteManager.registerForModemStateChanged(any(), any()))
.thenAnswer { invocation ->
val callback = invocation
- .getArgument<SatelliteModemStateCallback>(
- 1
- )
+ .getArgument<SatelliteModemStateCallback>(1)
callback.onSatelliteModemStateChanged(SATELLITE_MODEM_STATE_ENABLING_SATELLITE)
null
}
@@ -94,9 +92,7 @@
`when`(satelliteManager.registerForModemStateChanged(any(), any()))
.thenAnswer { invocation ->
val callback = invocation
- .getArgument<SatelliteModemStateCallback>(
- 1
- )
+ .getArgument<SatelliteModemStateCallback>(1)
callback.onSatelliteModemStateChanged(SATELLITE_MODEM_STATE_OFF)
null
}
@@ -136,4 +132,18 @@
verify(context, Times(0)).startActivity(any())
}
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+ fun mayStartSatelliteWarningDialog_phoneCrash_notShowWarningDialog() = runBlocking {
+ `when`(satelliteManager.registerForModemStateChanged(any(), any()))
+ .thenThrow(IllegalStateException("Telephony is null!!!"))
+
+ SatelliteDialogUtils.mayStartSatelliteWarningDialog(
+ context, coroutineScope, TYPE_IS_WIFI, allowClick = {
+ assertFalse(it)
+ })
+
+ verify(context, Times(0)).startActivity(any())
+ }
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
index 7b927d7..2823277 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
@@ -200,6 +200,7 @@
VALIDATORS.put(System.POINTER_LOCATION, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.SHOW_TOUCHES, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.SHOW_KEY_PRESSES, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(System.TOUCHPAD_VISUALIZER, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.SHOW_ROTARY_INPUT, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.WINDOW_ORIENTATION_LISTENER_LOG, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.LOCKSCREEN_SOUNDS_ENABLED, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index cd37ad1..3c24f5c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -2831,6 +2831,9 @@
Settings.System.SHOW_KEY_PRESSES,
SystemSettingsProto.DevOptions.SHOW_KEY_PRESSES);
dumpSetting(s, p,
+ Settings.System.TOUCHPAD_VISUALIZER,
+ SystemSettingsProto.DevOptions.TOUCHPAD_VISUALIZER);
+ dumpSetting(s, p,
Settings.System.POINTER_LOCATION,
SystemSettingsProto.DevOptions.POINTER_LOCATION);
dumpSetting(s, p,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index e8ef620..ba59ce8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3264,6 +3264,24 @@
if (forceNotify || success) {
notifyForSettingsChange(key, name);
+
+ // If this is an aconfig flag, it will be written as a staged flag.
+ // Notify that its staged flag value will be updated.
+ if (Flags.notifyIndividualAconfigSyspropChanged() && type == SETTINGS_TYPE_CONFIG) {
+ int slashIndex = name.indexOf('/');
+ boolean validSlashIndex = slashIndex != -1
+ && slashIndex != 0
+ && slashIndex != name.length();
+ if (validSlashIndex) {
+ String namespace = name.substring(0, slashIndex);
+ String flagName = name.substring(slashIndex + 1);
+ if (settingsState.getAconfigDefaultFlags().containsKey(flagName)) {
+ String stagedName = "staged/" + namespace + "*" + flagName;
+ notifyForSettingsChange(key, stagedName);
+ }
+ }
+ }
+
if (wasUnsetNonPredefinedSetting) {
// Increment the generation number for all non-predefined, unset settings,
// because a new non-predefined setting has been inserted
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/device_config_service.aconfig b/packages/SettingsProvider/src/com/android/providers/settings/device_config_service.aconfig
index 4f5955b..f53dec6 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/device_config_service.aconfig
+++ b/packages/SettingsProvider/src/com/android/providers/settings/device_config_service.aconfig
@@ -52,3 +52,14 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "notify_individual_aconfig_sysprop_changed"
+ namespace: "core_experiments_team_internal"
+ description: "When enabled, propagate individual aconfig sys props on flag stage."
+ bug: "331963764"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 411decd..8c96484 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -918,6 +918,7 @@
Settings.System.SHOW_GTALK_SERVICE_STATUS, // candidate for backup?
Settings.System.SHOW_TOUCHES,
Settings.System.SHOW_KEY_PRESSES,
+ Settings.System.TOUCHPAD_VISUALIZER,
Settings.System.SHOW_ROTARY_INPUT,
Settings.System.SIP_ADDRESS_ONLY, // value, not a setting
Settings.System.SIP_ALWAYS, // value, not a setting
diff --git a/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerActivity.java b/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerActivity.java
index 0dd9275..8c3cce4 100644
--- a/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerActivity.java
+++ b/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerActivity.java
@@ -255,8 +255,8 @@
p.mTitle = getString(com.android.internal.R.string.ringtone_picker_title);
}
} else {
- // Make sure intents don't inject HTML elements.
- p.mTitle = Html.escapeHtml(p.mTitle.toString());
+ // Make sure intents don't inject spannable elements.
+ p.mTitle = p.mTitle.toString();
}
setupAlert();
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index cfd8f635..c2e8c37 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -576,6 +576,7 @@
"TraceurCommon",
"Traceur-res",
"//frameworks/libs/systemui:motion_tool_lib",
+ "//frameworks/libs/systemui:contextualeducationlib",
"notification_flags_lib",
"PlatformComposeCore",
"PlatformComposeSceneTransitionLayout",
@@ -736,6 +737,7 @@
"WindowManager-Shell",
"LowLightDreamLib",
"//frameworks/libs/systemui:motion_tool_lib",
+ "//frameworks/libs/systemui:contextualeducationlib",
"androidx.core_core-animation-testing",
"androidx.compose.ui_ui",
"flag-junit",
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 92abc4c..9f3c2bf 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -1062,6 +1062,14 @@
</intent-filter>
</receiver>
+ <receiver android:name=".accessibility.extradim.ExtraDimDialogReceiver"
+ android:singleUser="true"
+ android:exported="false">
+ <intent-filter android:priority="1">
+ <action android:name="com.android.systemui.action.LAUNCH_REMOVE_EXTRA_DIM_DIALOG" />
+ </intent-filter>
+ </receiver>
+
<activity android:name=".logcat.LogAccessDialogActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:excludeFromRecents="true"
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
index d674b6c..c881e07 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
+++ b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
@@ -37,6 +37,7 @@
"androidx.core_core",
"androidx.preference_preference",
"androidx.viewpager_viewpager",
+ "com_android_systemui_flags_lib",
"SettingsLibDisplayUtils",
"SettingsLibSettingsTheme",
"com_android_a11y_menu_flags_lib",
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/AndroidManifest.xml b/packages/SystemUI/accessibility/accessibilitymenu/AndroidManifest.xml
index a98625f..a7b91c2 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/AndroidManifest.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/AndroidManifest.xml
@@ -18,6 +18,7 @@
package="com.android.systemui.accessibility.accessibilitymenu">
<uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS"/>
+ <uses-permission android:name="android.permission.MANAGE_USERS"/>
<application android:supportsRtl="true">
<service
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/aconfig/accessibility.aconfig b/packages/SystemUI/accessibility/accessibilitymenu/aconfig/accessibility.aconfig
index c1e43c9..6d79011 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/aconfig/accessibility.aconfig
+++ b/packages/SystemUI/accessibility/accessibilitymenu/aconfig/accessibility.aconfig
@@ -29,3 +29,13 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "hide_restricted_actions"
+ namespace: "accessibility"
+ description: "Hides shortcut buttons for possibly restricted actions like brightness/volume adjustment"
+ bug: "347269196"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
index 7b43b72..2e036e6 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
@@ -16,6 +16,8 @@
package com.android.systemui.accessibility.accessibilitymenu.view;
+import static android.os.UserManager.DISALLOW_ADJUST_VOLUME;
+import static android.os.UserManager.DISALLOW_CONFIG_BRIGHTNESS;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.View.ACCESSIBILITY_LIVE_REGION_POLITE;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
@@ -24,6 +26,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Insets;
@@ -32,6 +35,8 @@
import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.Looper;
+import android.os.UserHandle;
+import android.os.UserManager;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -48,6 +53,7 @@
import androidx.annotation.NonNull;
import com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService;
+import com.android.systemui.accessibility.accessibilitymenu.Flags;
import com.android.systemui.accessibility.accessibilitymenu.R;
import com.android.systemui.accessibility.accessibilitymenu.activity.A11yMenuSettingsActivity.A11yMenuPreferenceFragment;
import com.android.systemui.accessibility.accessibilitymenu.model.A11yMenuShortcut;
@@ -94,8 +100,6 @@
A11yMenuShortcut.ShortcutId.ID_SCREENSHOT_VALUE.ordinal()
};
-
-
private final AccessibilityMenuService mService;
private final WindowManager mWindowManager;
private final DisplayManager mDisplayManager;
@@ -195,11 +199,43 @@
for (int shortcutId :
(A11yMenuPreferenceFragment.isLargeButtonsEnabled(mService)
? LARGE_SHORTCUT_LIST_DEFAULT : SHORTCUT_LIST_DEFAULT)) {
- shortcutList.add(new A11yMenuShortcut(shortcutId));
+ if (!isShortcutRestricted(shortcutId)) {
+ shortcutList.add(new A11yMenuShortcut(shortcutId));
+ }
}
return shortcutList;
}
+ @SuppressLint("MissingPermission")
+ private boolean isShortcutRestricted(int shortcutId) {
+ if (!Flags.hideRestrictedActions()) {
+ return false;
+ }
+ final UserManager userManager = mService.getSystemService(UserManager.class);
+ if (userManager == null) {
+ return false;
+ }
+ final int userId = mService.getUserId();
+ final UserHandle userHandle = UserHandle.of(userId);
+ if (shortcutId == A11yMenuShortcut.ShortcutId.ID_BRIGHTNESS_DOWN_VALUE.ordinal()
+ || shortcutId == A11yMenuShortcut.ShortcutId.ID_BRIGHTNESS_UP_VALUE.ordinal()) {
+ if (userManager.hasUserRestriction(DISALLOW_CONFIG_BRIGHTNESS)
+ || (com.android.systemui.Flags.enforceBrightnessBaseUserRestriction()
+ && userManager.hasBaseUserRestriction(
+ DISALLOW_CONFIG_BRIGHTNESS, userHandle))) {
+ return true;
+ }
+ }
+ if (shortcutId == A11yMenuShortcut.ShortcutId.ID_VOLUME_DOWN_VALUE.ordinal()
+ || shortcutId == A11yMenuShortcut.ShortcutId.ID_VOLUME_UP_VALUE.ordinal()) {
+ if (userManager.hasUserRestriction(DISALLOW_ADJUST_VOLUME)
+ || userManager.hasBaseUserRestriction(DISALLOW_ADJUST_VOLUME, userHandle)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/** Updates a11y menu layout position by configuring layout params. */
private void updateLayoutPosition() {
final Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
@@ -326,8 +362,7 @@
return;
}
snackbar.setText(text);
- if (com.android.systemui.accessibility.accessibilitymenu
- .Flags.a11yMenuSnackbarLiveRegion()) {
+ if (Flags.a11yMenuSnackbarLiveRegion()) {
snackbar.setAccessibilityLiveRegion(ACCESSIBILITY_LIVE_REGION_POLITE);
}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp
index 395354e..9d5a2e0 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp
+++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp
@@ -31,6 +31,7 @@
"androidx.test.core",
"androidx.test.runner",
"androidx.test.ext.junit",
+ "com_android_a11y_menu_flags_lib",
"compatibility-device-util-axt",
"platform-test-annotations",
"truth",
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/AndroidManifest.xml b/packages/SystemUI/accessibility/accessibilitymenu/tests/AndroidManifest.xml
index 2be9245..40f71c5 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/tests/AndroidManifest.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/AndroidManifest.xml
@@ -20,6 +20,7 @@
<!-- Needed to write to Settings.Secure to enable and disable the service under test. -->
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS"/>
+ <uses-permission android:name="android.permission.MANAGE_USERS"/>
<application android:debuggable="true">
<uses-library android:name="android.test.runner" />
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java b/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java
index 991ce12..d16617f 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java
@@ -45,6 +45,10 @@
import android.hardware.display.DisplayManager;
import android.media.AudioManager;
import android.os.PowerManager;
+import android.os.UserManager;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.platform.uiautomator_helpers.WaitUtils;
import android.provider.Settings;
import android.util.Log;
@@ -59,6 +63,7 @@
import androidx.test.uiautomator.UiDevice;
import com.android.compatibility.common.util.TestUtils;
+import com.android.systemui.accessibility.accessibilitymenu.Flags;
import com.android.systemui.accessibility.accessibilitymenu.model.A11yMenuShortcut.ShortcutId;
import org.junit.After;
@@ -66,6 +71,7 @@
import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -76,6 +82,9 @@
@RunWith(AndroidJUnit4.class)
public class AccessibilityMenuServiceTest {
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
private static final String TAG = "A11yMenuServiceTest";
private static final int CLICK_ID = AccessibilityNodeInfo.ACTION_CLICK;
@@ -121,26 +130,8 @@
sDisplayManager = context.getSystemService(DisplayManager.class);
unlockSignal();
- // Disable all a11yServices if any are active.
- if (!sAccessibilityManager.getEnabledAccessibilityServiceList(
- AccessibilityServiceInfo.FEEDBACK_ALL_MASK).isEmpty()) {
- Settings.Secure.putString(context.getContentResolver(),
- Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, "");
- TestUtils.waitUntil("Failed to disable all services",
- TIMEOUT_SERVICE_STATUS_CHANGE_S,
- () -> sAccessibilityManager.getEnabledAccessibilityServiceList(
- AccessibilityServiceInfo.FEEDBACK_ALL_MASK).isEmpty());
- }
+ enableA11yMenuService(context);
- // Enable a11yMenu service.
- Settings.Secure.putString(context.getContentResolver(),
- Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, SERVICE_NAME);
-
- TestUtils.waitUntil("Failed to enable service",
- TIMEOUT_SERVICE_STATUS_CHANGE_S,
- () -> sAccessibilityManager.getEnabledAccessibilityServiceList(
- AccessibilityServiceInfo.FEEDBACK_ALL_MASK).stream().filter(
- info -> info.getId().contains(SERVICE_NAME)).count() == 1);
context.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -184,6 +175,29 @@
sUiDevice.pressHome();
}
+ private static void enableA11yMenuService(Context context) throws Throwable {
+ // Disable all a11yServices if any are active.
+ if (!sAccessibilityManager.getEnabledAccessibilityServiceList(
+ AccessibilityServiceInfo.FEEDBACK_ALL_MASK).isEmpty()) {
+ Settings.Secure.putString(context.getContentResolver(),
+ Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, "");
+ TestUtils.waitUntil("Failed to disable all services",
+ TIMEOUT_SERVICE_STATUS_CHANGE_S,
+ () -> sAccessibilityManager.getEnabledAccessibilityServiceList(
+ AccessibilityServiceInfo.FEEDBACK_ALL_MASK).isEmpty());
+ }
+
+ // Enable a11yMenu service.
+ Settings.Secure.putString(context.getContentResolver(),
+ Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, SERVICE_NAME);
+
+ TestUtils.waitUntil("Failed to enable service",
+ TIMEOUT_SERVICE_STATUS_CHANGE_S,
+ () -> sAccessibilityManager.getEnabledAccessibilityServiceList(
+ AccessibilityServiceInfo.FEEDBACK_ALL_MASK).stream().filter(
+ info -> info.getId().contains(SERVICE_NAME)).count() == 1);
+ }
+
private static boolean isMenuVisible() {
sUiDevice.waitForIdle();
AccessibilityNodeInfo root = sUiAutomation.getRootInActiveWindow();
@@ -484,6 +498,54 @@
sOpenBlocked::get);
}
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_HIDE_RESTRICTED_ACTIONS)
+ public void testRestrictedActions_BrightnessNotAvailable() throws Throwable {
+ try {
+ setUserRestriction(UserManager.DISALLOW_CONFIG_BRIGHTNESS, true);
+ openMenu();
+
+ List<AccessibilityNodeInfo> buttons = getGridButtonList();
+ AccessibilityNodeInfo brightnessUpButton = findGridButtonInfo(buttons,
+ String.valueOf(ShortcutId.ID_BRIGHTNESS_UP_VALUE.ordinal()));
+ AccessibilityNodeInfo brightnessDownButton = findGridButtonInfo(buttons,
+ String.valueOf(ShortcutId.ID_BRIGHTNESS_DOWN_VALUE.ordinal()));
+
+ assertThat(brightnessUpButton).isNull();
+ assertThat(brightnessDownButton).isNull();
+ } finally {
+ setUserRestriction(UserManager.DISALLOW_CONFIG_BRIGHTNESS, false);
+ }
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_HIDE_RESTRICTED_ACTIONS)
+ public void testRestrictedActions_VolumeNotAvailable() throws Throwable {
+ try {
+ setUserRestriction(UserManager.DISALLOW_ADJUST_VOLUME, true);
+ openMenu();
+
+ List<AccessibilityNodeInfo> buttons = getGridButtonList();
+ AccessibilityNodeInfo volumeUpButton = findGridButtonInfo(buttons,
+ String.valueOf(ShortcutId.ID_VOLUME_UP_VALUE.ordinal()));
+ AccessibilityNodeInfo volumeDownButton = findGridButtonInfo(buttons,
+ String.valueOf(ShortcutId.ID_VOLUME_DOWN_VALUE.ordinal()));
+
+ assertThat(volumeUpButton).isNull();
+ assertThat(volumeDownButton).isNull();
+ } finally {
+ setUserRestriction(UserManager.DISALLOW_ADJUST_VOLUME, false);
+ }
+ }
+
+ private void setUserRestriction(String restriction, boolean isRestricted) throws Throwable {
+ final Context context = sInstrumentation.getTargetContext();
+ final UserManager userManager = context.getSystemService(UserManager.class);
+ userManager.setUserRestriction(restriction, isRestricted);
+ // Re-enable the service for the restriction to take effect.
+ enableA11yMenuService(context);
+ }
+
private static void unlockSignal() throws IOException {
// go/adb-cheats#unlock-screen
wakeUpScreen();
diff --git a/packages/SystemUI/aconfig/biometrics_framework.aconfig b/packages/SystemUI/aconfig/biometrics_framework.aconfig
index bd1a442..e81d5d5 100644
--- a/packages/SystemUI/aconfig/biometrics_framework.aconfig
+++ b/packages/SystemUI/aconfig/biometrics_framework.aconfig
@@ -4,13 +4,6 @@
# NOTE: Keep alphabetized to help limit merge conflicts from multiple simultaneous editors.
flag {
- name: "bp_talkback"
- namespace: "biometrics_framework"
- description: "Adds talkback directional guidance when using UDFPS with biometric prompt"
- bug: "310044658"
-}
-
-flag {
name: "constraint_bp"
namespace: "biometrics_framework"
description: "Refactors Biometric Prompt to use a ConstraintLayout"
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 1f1495a..197dc6a 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -227,17 +227,6 @@
}
flag {
- name: "notification_group_hun_removal_animation_fix"
- namespace: "systemui"
- description: "Fix the lack of hun removal animation for group notifications"
- "(not GROUP_ALERT_SUMMARY)"
- bug: "343475993"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "scene_container"
namespace: "systemui"
description: "Enables the scene container framework go/flexiglass."
@@ -363,17 +352,6 @@
}
flag {
- name: "truncated_status_bar_icons_fix"
- namespace: "systemui"
- description: "Fixes the status bar icons being trunacted due to the status bar window height "
- "not being updated after certain rotations"
- bug: "323299264"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "status_bar_monochrome_icons_fix"
namespace: "systemui"
description: "Fixes the status bar icon size when drawing InsetDrawables (ie. monochrome icons)"
@@ -392,6 +370,24 @@
}
flag {
+ name: "status_bar_use_repos_for_call_chip"
+ namespace: "systemui"
+ description: "Use repositories as the source of truth for call notifications shown as a chip in"
+ "the status bar"
+ bug: "328584859"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "status_bar_call_chip_notification_icon"
+ namespace: "systemui"
+ description: "Use the small icon set on the notification for the status bar call chip"
+ bug: "354930838"
+}
+
+flag {
name: "compose_bouncer"
namespace: "systemui"
description: "Use the new compose bouncer in SystemUI"
@@ -571,16 +567,6 @@
}
flag {
- name: "screenshot_private_profile_accessibility_announcement_fix"
- namespace: "systemui"
- description: "Modified a11y announcement for private space screenshots"
- bug: "326941376"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "screenshot_private_profile_behavior_fix"
namespace: "systemui"
description: "Private profile support for screenshots"
@@ -1263,6 +1249,16 @@
}
flag {
+ name: "use_transitions_for_keyguard_occluded"
+ namespace: "systemui"
+ description: "Use Keyguard Transitions to set Notification Shade occlusion state"
+ bug: "344716537"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "lockscreen_preview_renderer_create_on_main_thread"
namespace: "systemui"
description: "Force preview renderer to be created on the main thread"
@@ -1280,3 +1276,10 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "compose_haptic_sliders"
+ namespace: "systemui"
+ description: "Adding haptic component infrastructure to sliders in Compose."
+ bug: "341968766"
+}
\ No newline at end of file
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
index 368085f..d4bad23 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
@@ -36,7 +36,7 @@
import com.android.compose.animation.scene.Edge
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.ElementMatcher
-import com.android.compose.animation.scene.LowestZIndexScenePicker
+import com.android.compose.animation.scene.LowestZIndexContentPicker
import com.android.compose.animation.scene.MutableSceneTransitionLayoutState
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.SceneScope
@@ -62,7 +62,7 @@
object Communal {
object Elements {
- val Scrim = ElementKey("Scrim", scenePicker = LowestZIndexScenePicker)
+ val Scrim = ElementKey("Scrim", contentPicker = LowestZIndexContentPicker)
val Grid = ElementKey("CommunalContent")
val LockIcon = ElementKey("CommunalLockIcon")
val IndicationArea = ElementKey("CommunalIndicationArea")
@@ -134,7 +134,7 @@
}
// Disable horizontal overscroll. If the scene is overscrolled too soon after showing, this
// can lead to inconsistent KeyguardState changes.
- overscroll(CommunalScenes.Communal, Orientation.Horizontal) {}
+ overscrollDisabled(CommunalScenes.Communal, Orientation.Horizontal)
}
/**
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
index 4c29e79..69f1174 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
@@ -244,48 +244,59 @@
.semantics { testTagsAsResourceId = true }
.testTag(COMMUNAL_HUB_TEST_TAG)
.fillMaxSize()
- .nestedScroll(nestedScrollConnection)
- .pointerInput(layoutDirection, gridState, contentOffset, contentListState) {
- awaitPointerEventScope {
- while (true) {
- var event = awaitFirstDown(requireUnconsumed = false)
- // Reset touch on first event.
- viewModel.onResetTouchState()
-
- // Process down event in case it's consumed immediately
- if (event.isConsumed) {
- viewModel.onHubTouchConsumed()
- }
-
- do {
- var event = awaitPointerEvent()
- for (change in event.changes) {
- if (change.isConsumed) {
- // Signal touch consumption on any consumed event.
- viewModel.onHubTouchConsumed()
- }
- }
- } while (
- !event.changes.fastAll {
- it.changedToUp() || it.changedToUpIgnoreConsumed()
- }
- )
+ // Observe taps for selecting items
+ .thenIf(viewModel.isEditMode) {
+ Modifier.pointerInput(
+ layoutDirection,
+ gridState,
+ contentOffset,
+ contentListState,
+ ) {
+ observeTaps { offset ->
+ // if RTL, flip offset direction from Left side to Right
+ val adjustedOffset =
+ Offset(
+ if (layoutDirection == LayoutDirection.Rtl)
+ screenWidth - offset.x
+ else offset.x,
+ offset.y
+ ) - contentOffset
+ val index = firstIndexAtOffset(gridState, adjustedOffset)
+ val key =
+ index?.let { keyAtIndexIfEditable(contentListState.list, index) }
+ viewModel.setSelectedKey(key)
}
}
+ }
+ // Nested scroll for full screen swipe to get to shade and bouncer
+ .thenIf(!viewModel.isEditMode) {
+ Modifier.nestedScroll(nestedScrollConnection).pointerInput(viewModel) {
+ awaitPointerEventScope {
+ while (true) {
+ val firstDownEvent = awaitFirstDown(requireUnconsumed = false)
+ // Reset touch on first event.
+ viewModel.onResetTouchState()
- // If not in edit mode, don't allow selecting items.
- if (!viewModel.isEditMode) return@pointerInput
- observeTaps { offset ->
- // if RTL, flip offset direction from Left side to Right
- val adjustedOffset =
- Offset(
- if (layoutDirection == LayoutDirection.Rtl) screenWidth - offset.x
- else offset.x,
- offset.y
- ) - contentOffset
- val index = firstIndexAtOffset(gridState, adjustedOffset)
- val key = index?.let { keyAtIndexIfEditable(contentListState.list, index) }
- viewModel.setSelectedKey(key)
+ // Process down event in case it's consumed immediately
+ if (firstDownEvent.isConsumed) {
+ viewModel.onHubTouchConsumed()
+ }
+
+ do {
+ val event = awaitPointerEvent()
+ for (change in event.changes) {
+ if (change.isConsumed) {
+ // Signal touch consumption on any consumed event.
+ viewModel.onHubTouchConsumed()
+ }
+ }
+ } while (
+ !event.changes.fastAll {
+ it.changedToUp() || it.changedToUpIgnoreConsumed()
+ }
+ )
+ }
+ }
}
}
.thenIf(!viewModel.isEditMode && !isEmptyState) {
@@ -293,7 +304,7 @@
gridState,
contentOffset,
communalContent,
- gridCoordinates
+ gridCoordinates,
) {
detectLongPressGesture { offset ->
// Deduct both grid offset relative to its container and content
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt
index 6feaf6d..9c72d93 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt
@@ -71,7 +71,7 @@
applyPadding: Boolean,
modifier: Modifier = Modifier,
) {
- MovableElement(
+ Element(
key = if (isStart) StartButtonElementKey else EndButtonElementKey,
modifier = modifier,
) {
@@ -98,7 +98,7 @@
fun SceneScope.IndicationArea(
modifier: Modifier = Modifier,
) {
- MovableElement(
+ Element(
key = IndicationAreaElementKey,
modifier = modifier.indicationAreaPadding(),
) {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt
index 218779d..bcdb259 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt
@@ -120,7 +120,7 @@
)
}
- MovableElement(key = largeClockElementKey, modifier = modifier) {
+ Element(key = largeClockElementKey, modifier = modifier) {
content {
AndroidView(
factory = { context ->
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/SmartSpaceSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/SmartSpaceSection.kt
index 44bda95..33ed14b 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/SmartSpaceSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/SmartSpaceSection.kt
@@ -65,68 +65,74 @@
) {
val resources = LocalContext.current.resources
- MovableElement(key = ClockElementKeys.smartspaceElementKey, modifier = modifier) {
- Column(
- modifier =
- modifier
- .onTopPlacementChanged(onTopChanged)
- .padding(
- top = { lockscreenContentViewModel.getSmartSpacePaddingTop(resources) },
- bottom = {
- resources.getDimensionPixelSize(
- R.dimen.keyguard_status_view_bottom_margin
- )
- }
- )
- ) {
- if (!keyguardSmartspaceViewModel.isSmartspaceEnabled) {
- return@Column
- }
+ Element(key = ClockElementKeys.smartspaceElementKey, modifier = modifier) {
+ content {
+ Column(
+ modifier =
+ modifier
+ .onTopPlacementChanged(onTopChanged)
+ .padding(
+ top = {
+ lockscreenContentViewModel.getSmartSpacePaddingTop(resources)
+ },
+ bottom = {
+ resources.getDimensionPixelSize(
+ R.dimen.keyguard_status_view_bottom_margin
+ )
+ }
+ )
+ ) {
+ if (!keyguardSmartspaceViewModel.isSmartspaceEnabled) {
+ return@Column
+ }
- val paddingBelowClockStart = dimensionResource(R.dimen.below_clock_padding_start)
- val paddingBelowClockEnd = dimensionResource(R.dimen.below_clock_padding_end)
+ val paddingBelowClockStart =
+ dimensionResource(R.dimen.below_clock_padding_start)
+ val paddingBelowClockEnd = dimensionResource(R.dimen.below_clock_padding_end)
- if (keyguardSmartspaceViewModel.isDateWeatherDecoupled) {
- Row(
- verticalAlignment = Alignment.CenterVertically,
+ if (keyguardSmartspaceViewModel.isDateWeatherDecoupled) {
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ modifier =
+ Modifier.fillMaxWidth()
+ // All items will be constrained to be as tall as the shortest
+ // item.
+ .height(IntrinsicSize.Min)
+ .padding(
+ start = paddingBelowClockStart,
+ ),
+ ) {
+ Date(
+ modifier =
+ Modifier.burnInAware(
+ viewModel = aodBurnInViewModel,
+ params = burnInParams,
+ ),
+ )
+ Spacer(modifier = Modifier.width(4.dp))
+ Weather(
+ modifier =
+ Modifier.burnInAware(
+ viewModel = aodBurnInViewModel,
+ params = burnInParams,
+ ),
+ )
+ }
+ }
+
+ Card(
modifier =
Modifier.fillMaxWidth()
- // All items will be constrained to be as tall as the shortest item.
- .height(IntrinsicSize.Min)
.padding(
start = paddingBelowClockStart,
- ),
- ) {
- Date(
- modifier =
- Modifier.burnInAware(
+ end = paddingBelowClockEnd,
+ )
+ .burnInAware(
viewModel = aodBurnInViewModel,
params = burnInParams,
),
- )
- Spacer(modifier = Modifier.width(4.dp))
- Weather(
- modifier =
- Modifier.burnInAware(
- viewModel = aodBurnInViewModel,
- params = burnInParams,
- ),
- )
- }
+ )
}
-
- Card(
- modifier =
- Modifier.fillMaxWidth()
- .padding(
- start = paddingBelowClockStart,
- end = paddingBelowClockEnd,
- )
- .burnInAware(
- viewModel = aodBurnInViewModel,
- params = burnInParams,
- ),
- )
}
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt
index 9a82da2..2e39524 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt
@@ -128,7 +128,7 @@
elementKey: ElementKey,
modifier: Modifier = Modifier,
) {
- MovableElement(key = elementKey, modifier) {
+ Element(key = elementKey, modifier) {
content {
AndroidView(
factory = {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt b/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt
index f8bd633..26ab10b 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt
@@ -28,7 +28,7 @@
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.viewinterop.AndroidView
-import com.android.compose.animation.scene.ElementKey
+import com.android.compose.animation.scene.MovableElementKey
import com.android.compose.animation.scene.SceneScope
import com.android.systemui.media.controls.ui.controller.MediaCarouselController
import com.android.systemui.media.controls.ui.view.MediaHost
@@ -38,7 +38,10 @@
object MediaCarousel {
object Elements {
internal val Content =
- ElementKey(debugName = "MediaCarouselContent", scenePicker = MediaScenePicker)
+ MovableElementKey(
+ debugName = "MediaCarouselContent",
+ contentPicker = MediaContentPicker,
+ )
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaScenePicker.kt b/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaContentPicker.kt
similarity index 62%
rename from packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaScenePicker.kt
rename to packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaContentPicker.kt
index 7b497e8..3f04f37 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaScenePicker.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaContentPicker.kt
@@ -16,18 +16,19 @@
package com.android.systemui.media.controls.ui.composable
+import com.android.compose.animation.scene.ContentKey
+import com.android.compose.animation.scene.ElementContentPicker
import com.android.compose.animation.scene.ElementKey
-import com.android.compose.animation.scene.ElementScenePicker
-import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.SceneTransitionLayoutState
-import com.android.compose.animation.scene.TransitionState
+import com.android.compose.animation.scene.StaticElementContentPicker
+import com.android.compose.animation.scene.content.state.ContentState
import com.android.systemui.scene.shared.model.Scenes
-/** [ElementScenePicker] implementation for the media carousel object. */
-object MediaScenePicker : ElementScenePicker {
+/** [ElementContentPicker] implementation for the media carousel object. */
+object MediaContentPicker : StaticElementContentPicker {
const val SHADE_FRACTION = 0.66f
- private val scenes =
+ override val contents =
setOf(
Scenes.Lockscreen,
Scenes.Shade,
@@ -36,12 +37,12 @@
Scenes.Communal
)
- override fun sceneDuringTransition(
+ override fun contentDuringTransition(
element: ElementKey,
- transition: TransitionState.Transition,
- fromSceneZIndex: Float,
- toSceneZIndex: Float
- ): SceneKey? {
+ transition: ContentState.Transition<*>,
+ fromContentZIndex: Float,
+ toContentZIndex: Float
+ ): ContentKey {
return when {
shouldElevateMedia(transition) -> {
Scenes.Shade
@@ -52,22 +53,23 @@
transition.isTransitioningBetween(Scenes.QuickSettings, Scenes.Shade) -> {
Scenes.QuickSettings
}
+ transition.toContent in contents -> transition.toContent
else -> {
- when {
- scenes.contains(transition.toScene) -> transition.toScene
- scenes.contains(transition.fromScene) -> transition.fromScene
- else -> null
+ check(transition.fromContent in contents) {
+ "Media player should not be composed for the transition from " +
+ "${transition.fromContent} to ${transition.toContent}"
}
+ transition.fromContent
}
}
}
/** Returns true when the media should be laid on top of the rest for the given [transition]. */
- fun shouldElevateMedia(transition: TransitionState.Transition): Boolean {
+ fun shouldElevateMedia(transition: ContentState.Transition<*>): Boolean {
return transition.isTransitioningBetween(Scenes.Lockscreen, Scenes.Shade)
}
}
-fun MediaScenePicker.shouldElevateMedia(layoutState: SceneTransitionLayoutState): Boolean {
+fun MediaContentPicker.shouldElevateMedia(layoutState: SceneTransitionLayoutState): Boolean {
return layoutState.currentTransition?.let { shouldElevateMedia(it) } ?: false
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
index 2eb7b3f..84782fd 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
@@ -78,7 +78,7 @@
import androidx.compose.ui.util.lerp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.scene.ElementKey
-import com.android.compose.animation.scene.LowestZIndexScenePicker
+import com.android.compose.animation.scene.LowestZIndexContentPicker
import com.android.compose.animation.scene.NestedScrollBehavior
import com.android.compose.animation.scene.SceneScope
import com.android.compose.modifiers.thenIf
@@ -105,7 +105,7 @@
val NotificationScrim = ElementKey("NotificationScrim")
val NotificationStackPlaceholder = ElementKey("NotificationStackPlaceholder")
val HeadsUpNotificationPlaceholder =
- ElementKey("HeadsUpNotificationPlaceholder", scenePicker = LowestZIndexScenePicker)
+ ElementKey("HeadsUpNotificationPlaceholder", contentPicker = LowestZIndexContentPicker)
val ShelfSpace = ElementKey("ShelfSpace")
val NotificationStackCutoffGuideline = ElementKey("NotificationStackCutoffGuideline")
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt
index 8058dcd..f399436 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt
@@ -33,10 +33,11 @@
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.scene.ElementKey
-import com.android.compose.animation.scene.MovableElementScenePicker
+import com.android.compose.animation.scene.MovableElementContentPicker
+import com.android.compose.animation.scene.MovableElementKey
import com.android.compose.animation.scene.SceneScope
-import com.android.compose.animation.scene.TransitionState
import com.android.compose.animation.scene.ValueKey
+import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.modifiers.thenIf
import com.android.systemui.compose.modifiers.sysuiResTag
import com.android.systemui.qs.ui.adapter.QSSceneAdapter
@@ -55,7 +56,10 @@
object Elements {
val Content =
- ElementKey("QuickSettingsContent", scenePicker = MovableElementScenePicker(SCENES))
+ MovableElementKey(
+ "QuickSettingsContent",
+ contentPicker = MovableElementContentPicker(SCENES)
+ )
val QuickQuickSettings = ElementKey("QuickQuickSettings")
val SplitShadeQuickSettings = ElementKey("SplitShadeQuickSettings")
val FooterActions = ElementKey("QuickSettingsFooterActions")
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
index 2800eee..cdcd840 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
@@ -68,11 +68,11 @@
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.scene.SceneScope
-import com.android.compose.animation.scene.TransitionState
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.compose.animation.scene.animateSceneDpAsState
import com.android.compose.animation.scene.animateSceneFloatAsState
+import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.modifiers.thenIf
import com.android.compose.windowsizeclass.LocalWindowSizeClass
import com.android.systemui.battery.BatteryMeterViewController
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
index e433d32..8751ca7 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
@@ -87,7 +87,7 @@
// Scene overscroll
- overscroll(Scenes.Gone, Orientation.Vertical) {}
+ overscrollDisabled(Scenes.Gone, Orientation.Vertical)
overscroll(Scenes.Bouncer, Orientation.Vertical) {
translate(Bouncer.Elements.Content, y = { absoluteDistance })
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToSplitShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToSplitShadeTransition.kt
index 2f8c248..a9da733 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToSplitShadeTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToSplitShadeTransition.kt
@@ -25,7 +25,7 @@
import com.android.compose.animation.scene.UserActionDistance
import com.android.compose.animation.scene.UserActionDistanceScope
import com.android.systemui.media.controls.ui.composable.MediaCarousel
-import com.android.systemui.media.controls.ui.composable.MediaScenePicker
+import com.android.systemui.media.controls.ui.composable.MediaContentPicker
import com.android.systemui.notifications.ui.composable.Notifications
import com.android.systemui.qs.ui.composable.QuickSettings
import com.android.systemui.shade.ui.composable.Shade
@@ -54,7 +54,8 @@
fractionRange(end = .33f) { fade(Shade.Elements.BackgroundScrim) }
fractionRange(start = .33f) {
- val qsTranslation = ShadeHeader.Dimensions.CollapsedHeight * MediaScenePicker.SHADE_FRACTION
+ val qsTranslation =
+ ShadeHeader.Dimensions.CollapsedHeight * MediaContentPicker.SHADE_FRACTION
val qsExpansionDiff =
ShadeHeader.Dimensions.ExpandedHeight - ShadeHeader.Dimensions.CollapsedHeight
translate(MediaCarousel.Elements.Content, y = -(qsExpansionDiff + qsTranslation))
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToShadeTransition.kt
index 7d46c75..21dfc49 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToShadeTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToShadeTransition.kt
@@ -26,7 +26,7 @@
import com.android.compose.animation.scene.UserActionDistance
import com.android.compose.animation.scene.UserActionDistanceScope
import com.android.systemui.media.controls.ui.composable.MediaCarousel
-import com.android.systemui.media.controls.ui.composable.MediaScenePicker
+import com.android.systemui.media.controls.ui.composable.MediaContentPicker
import com.android.systemui.notifications.ui.composable.Notifications
import com.android.systemui.qs.ui.composable.QuickSettings
import com.android.systemui.scene.shared.model.Scenes
@@ -62,7 +62,7 @@
fade(QuickSettings.Elements.FooterActions)
}
- val qsTranslation = ShadeHeader.Dimensions.CollapsedHeight * MediaScenePicker.SHADE_FRACTION
+ val qsTranslation = ShadeHeader.Dimensions.CollapsedHeight * MediaContentPicker.SHADE_FRACTION
val qsExpansionDiff =
ShadeHeader.Dimensions.ExpandedHeight - ShadeHeader.Dimensions.CollapsedHeight
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt
index 8656223..facbcaf 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt
@@ -49,7 +49,7 @@
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.scene.ElementKey
-import com.android.compose.animation.scene.LowestZIndexScenePicker
+import com.android.compose.animation.scene.LowestZIndexContentPicker
import com.android.compose.animation.scene.SceneScope
import com.android.compose.windowsizeclass.LocalWindowSizeClass
import com.android.systemui.keyguard.ui.composable.LockscreenContent
@@ -186,10 +186,10 @@
object OverlayShade {
object Elements {
- val Scrim = ElementKey("OverlayShadeScrim", scenePicker = LowestZIndexScenePicker)
- val Panel = ElementKey("OverlayShadePanel", scenePicker = LowestZIndexScenePicker)
+ val Scrim = ElementKey("OverlayShadeScrim", contentPicker = LowestZIndexContentPicker)
+ val Panel = ElementKey("OverlayShadePanel", contentPicker = LowestZIndexContentPicker)
val PanelBackground =
- ElementKey("OverlayShadePanelBackground", scenePicker = LowestZIndexScenePicker)
+ ElementKey("OverlayShadePanelBackground", contentPicker = LowestZIndexContentPicker)
}
object Colors {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
index b5a10ca..1cd48bf 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
@@ -59,11 +59,11 @@
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.scene.ElementKey
-import com.android.compose.animation.scene.LowestZIndexScenePicker
+import com.android.compose.animation.scene.LowestZIndexContentPicker
import com.android.compose.animation.scene.SceneScope
-import com.android.compose.animation.scene.TransitionState
import com.android.compose.animation.scene.ValueKey
import com.android.compose.animation.scene.animateElementFloatAsState
+import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.modifiers.thenIf
import com.android.compose.windowsizeclass.LocalWindowSizeClass
import com.android.settingslib.Utils
@@ -93,8 +93,8 @@
val ExpandedContent = ElementKey("ShadeHeaderExpandedContent")
val CollapsedContentStart = ElementKey("ShadeHeaderCollapsedContentStart")
val CollapsedContentEnd = ElementKey("ShadeHeaderCollapsedContentEnd")
- val PrivacyChip = ElementKey("PrivacyChip", scenePicker = LowestZIndexScenePicker)
- val Clock = ElementKey("ShadeHeaderClock", scenePicker = LowestZIndexScenePicker)
+ val PrivacyChip = ElementKey("PrivacyChip", contentPicker = LowestZIndexContentPicker)
+ val Clock = ElementKey("ShadeHeaderClock", contentPicker = LowestZIndexContentPicker)
val ShadeCarrierGroup = ElementKey("ShadeCarrierGroup")
}
@@ -110,6 +110,7 @@
object Colors {
val ColorScheme.shadeHeaderText: Color
get() = Color.White
+
val ColorScheme.onScrimDim: Color
get() = Color.DarkGray
}
@@ -148,8 +149,8 @@
}
val isLargeScreenLayout =
- LocalWindowSizeClass.current.widthSizeClass == WindowWidthSizeClass.Medium ||
- LocalWindowSizeClass.current.widthSizeClass == WindowWidthSizeClass.Expanded
+ LocalWindowSizeClass.current.widthSizeClass == WindowWidthSizeClass.Medium ||
+ LocalWindowSizeClass.current.widthSizeClass == WindowWidthSizeClass.Expanded
val isPrivacyChipVisible by viewModel.isPrivacyChipVisible.collectAsStateWithLifecycle()
@@ -197,8 +198,8 @@
) {
if (isLargeScreenLayout) {
ShadeCarrierGroup(
- viewModel = viewModel,
- modifier = Modifier.align(Alignment.CenterVertically),
+ viewModel = viewModel,
+ modifier = Modifier.align(Alignment.CenterVertically),
)
}
SystemIconContainer(
@@ -552,19 +553,20 @@
val interactionSource = remember { MutableInteractionSource() }
val isHovered by interactionSource.collectIsHoveredAsState()
- val hoverModifier = Modifier
- .clip(RoundedCornerShape(CollapsedHeight / 4))
+ val hoverModifier =
+ Modifier.clip(RoundedCornerShape(CollapsedHeight / 4))
.background(MaterialTheme.colorScheme.onScrimDim)
Row(
- modifier = modifier
+ modifier =
+ modifier
.height(CollapsedHeight)
.padding(vertical = CollapsedHeight / 4)
.thenIf(isClickable) {
Modifier.clickable(
- interactionSource = interactionSource,
- indication = null,
- onClick = { viewModel.onSystemIconContainerClicked() },
+ interactionSource = interactionSource,
+ indication = null,
+ onClick = { viewModel.onSystemIconContainerClicked() },
)
}
.thenIf(isHovered) { hoverModifier },
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
index 18ca0f7..77b48d3 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
@@ -63,14 +63,14 @@
import androidx.compose.ui.zIndex
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.scene.ElementKey
-import com.android.compose.animation.scene.LowestZIndexScenePicker
+import com.android.compose.animation.scene.LowestZIndexContentPicker
import com.android.compose.animation.scene.NestedScrollBehavior
import com.android.compose.animation.scene.SceneScope
-import com.android.compose.animation.scene.TransitionState
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.compose.animation.scene.animateSceneDpAsState
import com.android.compose.animation.scene.animateSceneFloatAsState
+import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.modifiers.padding
import com.android.compose.modifiers.thenIf
import com.android.compose.windowsizeclass.LocalWindowSizeClass
@@ -81,7 +81,7 @@
import com.android.systemui.compose.modifiers.sysuiResTag
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.media.controls.ui.composable.MediaCarousel
-import com.android.systemui.media.controls.ui.composable.MediaScenePicker
+import com.android.systemui.media.controls.ui.composable.MediaContentPicker
import com.android.systemui.media.controls.ui.composable.shouldElevateMedia
import com.android.systemui.media.controls.ui.controller.MediaCarouselController
import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager
@@ -118,7 +118,7 @@
object Elements {
val MediaCarousel = ElementKey("ShadeMediaCarousel")
val BackgroundScrim =
- ElementKey("ShadeBackgroundScrim", scenePicker = LowestZIndexScenePicker)
+ ElementKey("ShadeBackgroundScrim", contentPicker = LowestZIndexContentPicker)
val SplitShadeStartColumn = ElementKey("SplitShadeStartColumn")
}
@@ -376,7 +376,7 @@
layout(constraints.maxWidth, constraints.maxHeight) {
val qsZIndex =
- if (MediaScenePicker.shouldElevateMedia(layoutState)) {
+ if (MediaContentPicker.shouldElevateMedia(layoutState)) {
1f
} else {
0f
@@ -563,7 +563,7 @@
mediaHost = mediaHost,
modifier =
Modifier.fillMaxWidth().thenIf(
- MediaScenePicker.shouldElevateMedia(layoutState)
+ MediaContentPicker.shouldElevateMedia(layoutState)
) {
Modifier.zIndex(1f)
},
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
index afbc8e7..e13ca391 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
@@ -32,6 +32,7 @@
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastCoerceIn
import androidx.compose.ui.util.fastLastOrNull
+import com.android.compose.animation.scene.content.state.TransitionState
import kotlin.math.roundToInt
/**
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt
index 82c85d1..1fc1f98 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt
@@ -19,6 +19,7 @@
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.AnimationVector1D
import androidx.compose.animation.core.SpringSpec
+import com.android.compose.animation.scene.content.state.TransitionState
import kotlin.math.absoluteValue
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
index 67d1b59..a43028a 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
@@ -29,8 +29,11 @@
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.round
-import com.android.compose.animation.scene.TransitionState.HasOverscrollProperties.Companion.DistanceUnspecified
+import androidx.compose.ui.util.fastCoerceIn
import com.android.compose.animation.scene.content.Scene
+import com.android.compose.animation.scene.content.state.ContentState
+import com.android.compose.animation.scene.content.state.ContentState.HasOverscrollProperties.Companion.DistanceUnspecified
+import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.nestedscroll.PriorityNestedScrollConnection
import kotlin.math.absoluteValue
import kotlinx.coroutines.CoroutineScope
@@ -285,17 +288,66 @@
if (delta == 0f || !isDrivingTransition || swipeTransition.isFinishing) {
return 0f
}
- swipeTransition.dragOffset += delta
- val (fromScene, acceleratedOffset) =
- computeFromSceneConsideringAcceleratedSwipe(swipeTransition)
+ val toScene = swipeTransition._toScene
+ val distance = swipeTransition.distance()
+ val previousOffset = swipeTransition.dragOffset
+ val desiredOffset = previousOffset + delta
- val isNewFromScene = fromScene.key != swipeTransition.fromScene
+ fun hasReachedToSceneUpOrLeft() =
+ distance < 0 &&
+ desiredOffset <= distance &&
+ swipes.upOrLeftResult?.toScene == toScene.key
+
+ fun hasReachedToSceneDownOrRight() =
+ distance > 0 &&
+ desiredOffset >= distance &&
+ swipes.downOrRightResult?.toScene == toScene.key
+
+ // Considering accelerated swipe: Change fromScene in the case where the user quickly swiped
+ // multiple times in the same direction to accelerate the transition from A => B then B => C
+ //
+ // TODO(b/290184746): the second drag needs to pass B to work. Add support for flinging
+ // twice before B has been reached
+ val hasReachedToScene =
+ swipeTransition._currentScene == toScene &&
+ (hasReachedToSceneUpOrLeft() || hasReachedToSceneDownOrRight())
+
+ val fromScene: Scene
+ val currentTransitionOffset: Float
+ val newOffset: Float
+ val consumedDelta: Float
+ if (hasReachedToScene) {
+ // The new transition will start from the current toScene
+ fromScene = toScene
+ // The current transition is completed (we have reached the distance)
+ currentTransitionOffset = distance
+ // The next transition will start with the remaining offset
+ newOffset = desiredOffset - distance
+ consumedDelta = delta
+ } else {
+ fromScene = swipeTransition._fromScene
+ val desiredProgress = swipeTransition.computeProgress(desiredOffset)
+ // note: the distance could be negative if fromScene is aboveOrLeft of toScene.
+ currentTransitionOffset =
+ when {
+ distance == DistanceUnspecified ||
+ swipeTransition.isWithinProgressRange(desiredProgress) -> desiredOffset
+ distance > 0f -> desiredOffset.fastCoerceIn(0f, distance)
+ else -> desiredOffset.fastCoerceIn(distance, 0f)
+ }
+ // If there is a new transition, we will use the same offset
+ newOffset = currentTransitionOffset
+ consumedDelta = newOffset - previousOffset
+ }
+
+ swipeTransition.dragOffset = currentTransitionOffset
+
val result =
swipes.findUserActionResult(
fromScene = fromScene,
- directionOffset = swipeTransition.dragOffset,
- updateSwipesResults = isNewFromScene,
+ directionOffset = newOffset,
+ updateSwipesResults = hasReachedToScene
)
if (result == null) {
@@ -303,65 +355,30 @@
return 0f
}
- if (
- isNewFromScene ||
+ val needNewTransition =
+ hasReachedToScene ||
result.toScene != swipeTransition.toScene ||
result.transitionKey != swipeTransition.key
- ) {
+
+ if (needNewTransition) {
// Make sure the current transition will finish to the right current scene.
swipeTransition._currentScene = fromScene
- val swipeTransition =
+ val newSwipeTransition =
SwipeTransition(
- layoutState = layoutState,
- coroutineScope = draggableHandler.coroutineScope,
- fromScene = fromScene,
- result = result,
- swipes = swipes,
- layoutImpl = draggableHandler.layoutImpl,
- orientation = draggableHandler.orientation,
- )
- .apply { dragOffset = swipeTransition.dragOffset + acceleratedOffset }
-
- updateTransition(swipeTransition)
+ layoutState = layoutState,
+ coroutineScope = draggableHandler.coroutineScope,
+ fromScene = fromScene,
+ result = result,
+ swipes = swipes,
+ layoutImpl = draggableHandler.layoutImpl,
+ orientation = draggableHandler.orientation,
+ )
+ newSwipeTransition.dragOffset = newOffset
+ updateTransition(newSwipeTransition)
}
- return delta
- }
-
- /**
- * Change fromScene in the case where the user quickly swiped multiple times in the same
- * direction to accelerate the transition from A => B then B => C.
- *
- * @return the new fromScene and a dragOffset to be added in case the scene has changed
- *
- * TODO(b/290184746): the second drag needs to pass B to work. Add support for flinging twice
- * before B has been reached
- */
- private inline fun computeFromSceneConsideringAcceleratedSwipe(
- swipeTransition: SwipeTransition,
- ): Pair<Scene, Float> {
- val toScene = swipeTransition._toScene
- val fromScene = swipeTransition._fromScene
- val distance = swipeTransition.distance()
-
- // If the swipe was not committed or if the swipe distance is not computed yet, don't do
- // anything.
- if (swipeTransition._currentScene != toScene || distance == DistanceUnspecified) {
- return fromScene to 0f
- }
-
- // If the offset is past the distance then let's change fromScene so that the user can swipe
- // to the next screen or go back to the previous one.
- val offset = swipeTransition.dragOffset
- val absoluteDistance = distance.absoluteValue
- return if (offset <= -absoluteDistance && swipes.upOrLeftResult?.toScene == toScene.key) {
- toScene to absoluteDistance
- } else if (offset >= absoluteDistance && swipes.downOrRightResult?.toScene == toScene.key) {
- toScene to -absoluteDistance
- } else {
- fromScene to 0f
- }
+ return consumedDelta
}
override fun onStop(velocity: Float, canChangeScene: Boolean): Float {
@@ -593,7 +610,7 @@
var lastDistance: Float = DistanceUnspecified,
) :
TransitionState.Transition(_fromScene.key, _toScene.key, replacedTransition),
- TransitionState.HasOverscrollProperties {
+ ContentState.HasOverscrollProperties {
var _currentScene by mutableStateOf(_fromScene)
override val currentScene: SceneKey
get() = _currentScene.key
@@ -605,14 +622,17 @@
// subscribes to the offset value.
val offset = offsetAnimation?.animatable?.value ?: dragOffset
- val distance = distance()
- if (distance == DistanceUnspecified) {
- return 0f
- }
-
- return offset / distance
+ return computeProgress(offset)
}
+ fun computeProgress(offset: Float): Float {
+ val distance = distance()
+ if (distance == DistanceUnspecified) {
+ return 0f
+ }
+ return offset / distance
+ }
+
override val progressVelocity: Float
get() {
val animatable = offsetAnimation?.animatable ?: return 0f
@@ -627,7 +647,7 @@
override val isInitiatedByUserInput = true
- override var bouncingScene: SceneKey? = null
+ override var bouncingContent: SceneKey? = null
/** The current offset caused by the drag gesture. */
var dragOffset by mutableFloatStateOf(0f)
@@ -708,18 +728,19 @@
targetOffset: Float,
targetScene: SceneKey,
): OffsetAnimation {
+ val initialProgress = progress
// Skip the animation if we have already reached the target scene and the overscroll does
// not animate anything.
val hasReachedTargetScene =
- (targetScene == toScene && progress >= 1f) ||
- (targetScene == fromScene && progress <= 0f)
- val skipAnimation = hasReachedTargetScene && !canOverscroll()
+ (targetScene == toScene && initialProgress >= 1f) ||
+ (targetScene == fromScene && initialProgress <= 0f)
+ val skipAnimation = hasReachedTargetScene && !isWithinProgressRange(initialProgress)
return startOffsetAnimation {
val animatable = Animatable(dragOffset, OffsetVisibilityThreshold)
val isTargetGreater = targetOffset > animatable.value
val startedWhenOvercrollingTargetScene =
- if (targetScene == fromScene) progress < 0f else progress > 1f
+ if (targetScene == fromScene) initialProgress < 0f else initialProgress > 1f
val job =
coroutineScope
// Important: We start atomically to make sure that we start the coroutine even
@@ -745,7 +766,7 @@
animationSpec = swipeSpec,
initialVelocity = initialVelocity,
) {
- if (bouncingScene == null) {
+ if (bouncingContent == null) {
val isBouncing =
if (isTargetGreater) {
if (startedWhenOvercrollingTargetScene) {
@@ -762,11 +783,11 @@
}
if (isBouncing) {
- bouncingScene = targetScene
+ bouncingContent = targetScene
// Immediately stop this transition if we are bouncing on a
// scene that does not bounce.
- if (!canOverscroll()) {
+ if (!isWithinProgressRange(progress)) {
snapToScene(targetScene)
}
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
index 0b5e58f..ec7c77b 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
@@ -49,13 +49,15 @@
import androidx.compose.ui.util.fastLastOrNull
import androidx.compose.ui.util.lerp
import com.android.compose.animation.scene.content.Content
+import com.android.compose.animation.scene.content.state.ContentState
+import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.animation.scene.transformation.PropertyTransformation
import com.android.compose.animation.scene.transformation.SharedElementTransformation
import com.android.compose.ui.util.lerp
import kotlin.math.roundToInt
import kotlinx.coroutines.launch
-/** An element on screen, that can be composed in one or more scenes. */
+/** An element on screen, that can be composed in one or more contents. */
@Stable
internal class Element(val key: ElementKey) {
/** The mapping between a content and the state this element has in that content, if any. */
@@ -67,7 +69,7 @@
* The last transition that was used when computing the state (size, position and alpha) of this
* element in any content, or `null` if it was last laid out when idle.
*/
- var lastTransition: TransitionState.Transition? = null
+ var lastTransition: ContentState.Transition<*>? = null
/** Whether this element was ever drawn in a content. */
var wasDrawnInAnyContent = false
@@ -86,7 +88,7 @@
var targetSize by mutableStateOf(SizeUnspecified)
var targetOffset by mutableStateOf(Offset.Unspecified)
- /** The last state this element had in this scene. */
+ /** The last state this element had in this content. */
var lastOffset = Offset.Unspecified
var lastSize = SizeUnspecified
var lastScale = Scale.Unspecified
@@ -103,7 +105,7 @@
/**
* The delta values to add to this element state to have smoother interruptions. These
* should be multiplied by the
- * [current interruption progress][TransitionState.Transition.interruptionProgress] so that
+ * [current interruption progress][ContentState.Transition.interruptionProgress] so that
* they nicely animate from their values down to 0.
*/
var offsetInterruptionDelta = Offset.Zero
@@ -310,7 +312,7 @@
}
private fun Placeable.PlacementScope.place(
- transition: TransitionState.Transition?,
+ transition: ContentState.Transition<*>?,
placeable: Placeable,
) {
with(layoutImpl.lookaheadScope) {
@@ -475,7 +477,7 @@
layoutImpl: SceneTransitionLayoutImpl,
element: Element,
transitions: List<TransitionState.Transition>,
-): TransitionState.Transition? {
+): ContentState.Transition<*>? {
val transition =
transitions.fastLastOrNull { transition ->
transition.fromScene in element.stateByContent ||
@@ -502,8 +504,8 @@
private fun prepareInterruption(
layoutImpl: SceneTransitionLayoutImpl,
element: Element,
- transition: TransitionState.Transition,
- previousTransition: TransitionState.Transition,
+ transition: ContentState.Transition<*>,
+ previousTransition: ContentState.Transition<*>,
) {
if (transition.replacedTransition == previousTransition) {
return
@@ -514,10 +516,10 @@
return stateByContent[key]?.also { it.selfUpdateValuesBeforeInterruption() }
}
- val previousFromState = updateStateInContent(previousTransition.fromScene)
- val previousToState = updateStateInContent(previousTransition.toScene)
- val fromState = updateStateInContent(transition.fromScene)
- val toState = updateStateInContent(transition.toScene)
+ val previousFromState = updateStateInContent(previousTransition.fromContent)
+ val previousToState = updateStateInContent(previousTransition.toContent)
+ val fromState = updateStateInContent(transition.fromContent)
+ val toState = updateStateInContent(transition.toContent)
reconcileStates(element, previousTransition)
reconcileStates(element, transition)
@@ -545,31 +547,31 @@
}
/**
- * Reconcile the state of [element] in the fromScene and toScene of [transition] so that the values
- * before interruption have their expected values, taking shared transitions into account.
+ * Reconcile the state of [element] in the formContent and toContent of [transition] so that the
+ * values before interruption have their expected values, taking shared transitions into account.
*/
private fun reconcileStates(
element: Element,
- transition: TransitionState.Transition,
+ transition: ContentState.Transition<*>,
) {
- val fromSceneState = element.stateByContent[transition.fromScene] ?: return
- val toSceneState = element.stateByContent[transition.toScene] ?: return
+ val fromContentState = element.stateByContent[transition.fromContent] ?: return
+ val toContentState = element.stateByContent[transition.toContent] ?: return
if (!isSharedElementEnabled(element.key, transition)) {
return
}
if (
- fromSceneState.offsetBeforeInterruption != Offset.Unspecified &&
- toSceneState.offsetBeforeInterruption == Offset.Unspecified
+ fromContentState.offsetBeforeInterruption != Offset.Unspecified &&
+ toContentState.offsetBeforeInterruption == Offset.Unspecified
) {
- // Element is shared and placed in fromScene only.
- toSceneState.updateValuesBeforeInterruption(fromSceneState)
+ // Element is shared and placed in fromContent only.
+ toContentState.updateValuesBeforeInterruption(fromContentState)
} else if (
- toSceneState.offsetBeforeInterruption != Offset.Unspecified &&
- fromSceneState.offsetBeforeInterruption == Offset.Unspecified
+ toContentState.offsetBeforeInterruption != Offset.Unspecified &&
+ fromContentState.offsetBeforeInterruption == Offset.Unspecified
) {
- // Element is shared and placed in toScene only.
- fromSceneState.updateValuesBeforeInterruption(toSceneState)
+ // Element is shared and placed in toContent only.
+ fromContentState.updateValuesBeforeInterruption(toContentState)
}
}
@@ -614,12 +616,12 @@
/**
* Compute what [value] should be if we take the
- * [interruption progress][TransitionState.Transition.interruptionProgress] of [transition] into
+ * [interruption progress][ContentState.Transition.interruptionProgress] of [transition] into
* account.
*/
private inline fun <T> computeInterruptedValue(
layoutImpl: SceneTransitionLayoutImpl,
- transition: TransitionState.Transition?,
+ transition: ContentState.Transition<*>?,
value: T,
unspecifiedValue: T,
zeroValue: T,
@@ -660,13 +662,13 @@
/**
* Set the interruption delta of a *placement/drawing*-related value (offset, alpha, scale). This
- * ensures that the delta is also set on the other scene in the transition for shared elements, so
- * that there is no jump cut if the scene where the element is placed has changed.
+ * ensures that the delta is also set on the other content in the transition for shared elements, so
+ * that there is no jump cut if the content where the element is placed has changed.
*/
private inline fun <T> setPlacementInterruptionDelta(
element: Element,
stateInContent: Element.State,
- transition: TransitionState.Transition?,
+ transition: ContentState.Transition<*>?,
delta: T,
setter: (Element.State, T) -> Unit,
) {
@@ -677,14 +679,14 @@
return
}
- // If the element is shared, also set the delta on the other scene so that it is used by that
- // scene if we start overscrolling it and change the scene where the element is placed.
- val otherScene =
- if (stateInContent.content == transition.fromScene) transition.toScene
- else transition.fromScene
- val otherSceneState = element.stateByContent[otherScene] ?: return
+ // If the element is shared, also set the delta on the other content so that it is used by that
+ // content if we start overscrolling it and change the content where the element is placed.
+ val otherContent =
+ if (stateInContent.content == transition.fromContent) transition.toContent
+ else transition.fromContent
+ val otherContentState = element.stateByContent[otherContent] ?: return
if (isSharedElementEnabled(element.key, transition)) {
- setter(otherSceneState, delta)
+ setter(otherContentState, delta)
}
}
@@ -692,7 +694,7 @@
layoutImpl: SceneTransitionLayoutImpl,
content: ContentKey,
element: Element,
- transition: TransitionState.Transition?,
+ transition: ContentState.Transition<*>?,
): Boolean {
// Always place the element if we are idle.
if (transition == null) {
@@ -701,14 +703,14 @@
// Don't place the element in this content if this content is not part of the current element
// transition.
- if (content != transition.fromScene && content != transition.toScene) {
+ if (content != transition.fromContent && content != transition.toContent) {
return false
}
// Place the element if it is not shared.
if (
- transition.fromScene !in element.stateByContent ||
- transition.toScene !in element.stateByContent
+ transition.fromContent !in element.stateByContent ||
+ transition.toContent !in element.stateByContent
) {
return true
}
@@ -730,7 +732,7 @@
layoutImpl: SceneTransitionLayoutImpl,
content: ContentKey,
element: ElementKey,
- transition: TransitionState.Transition,
+ transition: ContentState.Transition<*>,
): Boolean {
// If we are overscrolling, only place/compose the element in the overscrolling scene.
val overscrollScene = transition.currentOverscrollSpec?.scene
@@ -738,45 +740,47 @@
return content == overscrollScene
}
- val scenePicker = element.scenePicker
- val fromScene = transition.fromScene
- val toScene = transition.toScene
-
+ val scenePicker = element.contentPicker
val pickedScene =
- scenePicker.sceneDuringTransition(
- element = element,
- transition = transition,
- fromSceneZIndex = layoutImpl.scenes.getValue(fromScene).zIndex,
- toSceneZIndex = layoutImpl.scenes.getValue(toScene).zIndex,
- ) ?: return false
+ when (transition) {
+ is TransitionState.Transition -> {
+ scenePicker.contentDuringTransition(
+ element = element,
+ transition = transition,
+ fromContentZIndex = layoutImpl.scene(transition.fromScene).zIndex,
+ toContentZIndex = layoutImpl.scene(transition.toScene).zIndex,
+ )
+ }
+ }
return pickedScene == content
}
private fun isSharedElementEnabled(
element: ElementKey,
- transition: TransitionState.Transition,
+ transition: ContentState.Transition<*>,
): Boolean {
return sharedElementTransformation(element, transition)?.enabled ?: true
}
internal fun sharedElementTransformation(
element: ElementKey,
- transition: TransitionState.Transition,
+ transition: ContentState.Transition<*>,
): SharedElementTransformation? {
val transformationSpec = transition.transformationSpec
- val sharedInFromScene = transformationSpec.transformations(element, transition.fromScene).shared
- val sharedInToScene = transformationSpec.transformations(element, transition.toScene).shared
+ val sharedInFromContent =
+ transformationSpec.transformations(element, transition.fromContent).shared
+ val sharedInToContent = transformationSpec.transformations(element, transition.toContent).shared
- // The sharedElement() transformation must either be null or be the same in both scenes.
- if (sharedInFromScene != sharedInToScene) {
+ // The sharedElement() transformation must either be null or be the same in both contents.
+ if (sharedInFromContent != sharedInToContent) {
error(
- "Different sharedElement() transformations matched $element (from=$sharedInFromScene " +
- "to=$sharedInToScene)"
+ "Different sharedElement() transformations matched $element " +
+ "(from=$sharedInFromContent to=$sharedInToContent)"
)
}
- return sharedInFromScene
+ return sharedInFromContent
}
/**
@@ -789,16 +793,14 @@
private fun isElementOpaque(
content: Content,
element: Element,
- transition: TransitionState.Transition?,
+ transition: ContentState.Transition<*>?,
): Boolean {
if (transition == null) {
return true
}
- val fromScene = transition.fromScene
- val toScene = transition.toScene
- val fromState = element.stateByContent[fromScene]
- val toState = element.stateByContent[toScene]
+ val fromState = element.stateByContent[transition.fromContent]
+ val toState = element.stateByContent[transition.toContent]
if (fromState == null && toState == null) {
// TODO(b/311600838): Throw an exception instead once layers of disposed elements are not
@@ -825,7 +827,7 @@
private fun elementAlpha(
layoutImpl: SceneTransitionLayoutImpl,
element: Element,
- transition: TransitionState.Transition?,
+ transition: ContentState.Transition<*>?,
stateInContent: Element.State,
): Float {
val alpha =
@@ -856,7 +858,7 @@
private fun interruptedAlpha(
layoutImpl: SceneTransitionLayoutImpl,
element: Element,
- transition: TransitionState.Transition?,
+ transition: ContentState.Transition<*>?,
stateInContent: Element.State,
alpha: Float,
): Float {
@@ -886,7 +888,7 @@
private fun measure(
layoutImpl: SceneTransitionLayoutImpl,
element: Element,
- transition: TransitionState.Transition?,
+ transition: ContentState.Transition<*>?,
stateInContent: Element.State,
measurable: Measurable,
constraints: Constraints,
@@ -950,7 +952,7 @@
private fun ContentDrawScope.getDrawScale(
layoutImpl: SceneTransitionLayoutImpl,
element: Element,
- transition: TransitionState.Transition?,
+ transition: ContentState.Transition<*>?,
stateInContent: Element.State,
): Scale {
val scale =
@@ -1031,7 +1033,7 @@
* @param layoutImpl the [SceneTransitionLayoutImpl] associated to [element].
* @param currentContentState the content state of the content for which we are computing the value.
* Note that during interruptions, this could be the state of a content that is neither
- * [transition.toScene] nor [transition.fromScene].
+ * [transition.toContent] nor [transition.fromContent].
* @param element the element being animated.
* @param contentValue the value being animated.
* @param transformation the transformation associated to the value being animated.
@@ -1046,7 +1048,7 @@
layoutImpl: SceneTransitionLayoutImpl,
currentContentState: Element.State,
element: Element,
- transition: TransitionState.Transition?,
+ transition: ContentState.Transition<*>?,
contentValue: (Element.State) -> T,
transformation: (ElementTransformations) -> PropertyTransformation<T>?,
currentValue: () -> T,
@@ -1061,11 +1063,11 @@
return currentValue()
}
- val fromScene = transition.fromScene
- val toScene = transition.toScene
+ val fromContent = transition.fromContent
+ val toContent = transition.toContent
- val fromState = element.stateByContent[fromScene]
- val toState = element.stateByContent[toScene]
+ val fromState = element.stateByContent[fromContent]
+ val toState = element.stateByContent[toContent]
if (fromState == null && toState == null) {
// TODO(b/311600838): Throw an exception instead once layers of disposed elements are not
@@ -1073,19 +1075,20 @@
return contentValue(currentContentState)
}
- val currentScene = currentContentState.content
- if (transition is TransitionState.HasOverscrollProperties) {
+ val currentContent = currentContentState.content
+ if (transition is ContentState.HasOverscrollProperties) {
val overscroll = transition.currentOverscrollSpec
- if (overscroll?.scene == currentScene) {
+ if (overscroll?.scene == currentContent) {
val elementSpec =
- overscroll.transformationSpec.transformations(element.key, currentScene)
+ overscroll.transformationSpec.transformations(element.key, currentContent)
val propertySpec = transformation(elementSpec) ?: return currentValue()
- val overscrollState = checkNotNull(if (currentScene == toScene) toState else fromState)
+ val overscrollState =
+ checkNotNull(if (currentContent == toContent) toState else fromState)
val idleValue = contentValue(overscrollState)
val targetValue =
propertySpec.transform(
layoutImpl,
- currentScene,
+ currentContent,
element,
overscrollState,
transition,
@@ -1101,8 +1104,8 @@
// TODO(b/290184746): Make sure that we don't overflow transformations associated to a
// range.
val directionSign = if (transition.isUpOrLeft) -1 else 1
- val isToScene = overscroll.scene == transition.toScene
- val linearProgress = transition.progress.let { if (isToScene) it - 1f else it }
+ val isToContent = overscroll.scene == transition.toContent
+ val linearProgress = transition.progress.let { if (isToContent) it - 1f else it }
val progress = directionSign * overscroll.progressConverter(linearProgress)
val rangeProgress = propertySpec.range?.progress(progress) ?: progress
@@ -1111,7 +1114,8 @@
}
}
- // The element is shared: interpolate between the value in fromScene and the value in toScene.
+ // The element is shared: interpolate between the value in fromContent and the value in
+ // toContent.
// TODO(b/290184746): Support non linear shared paths as well as a way to make sure that shared
// elements follow the finger direction.
val isSharedElement = fromState != null && toState != null
@@ -1134,15 +1138,15 @@
val contentState =
checkNotNull(
when {
- isSharedElement && currentScene == fromScene -> fromState
+ isSharedElement && currentContent == fromContent -> fromState
isSharedElement -> toState
else -> fromState ?: toState
}
)
- // The scene for which we compute the transformation. Note that this is not necessarily
- // [currentScene] because [currentScene] could be a different scene than the transition
- // fromScene or toScene during interruptions.
+ // The content for which we compute the transformation. Note that this is not necessarily
+ // [currentContent] because [currentContent] could be a different content than the transition
+ // fromContent or toContent during interruptions.
val content = contentState.content
val transformation =
@@ -1156,7 +1160,7 @@
val isInPreviewStage = transition.isInPreviewStage
val idleValue = contentValue(contentState)
- val isEntering = content == toScene
+ val isEntering = content == toContent
val previewTargetValue =
previewTransformation.transform(
layoutImpl,
@@ -1262,7 +1266,7 @@
val rangeProgress = transformation.range?.progress(progress) ?: progress
// Interpolate between the value at rest and the value before entering/after leaving.
- val isEntering = content == toScene
+ val isEntering = content == toContent
return if (isEntering) {
lerp(targetValue, idleValue, rangeProgress)
} else {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/InterruptionHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/InterruptionHandler.kt
index 54c64fd..bf70ca9 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/InterruptionHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/InterruptionHandler.kt
@@ -16,6 +16,8 @@
package com.android.compose.animation.scene
+import com.android.compose.animation.scene.content.state.TransitionState
+
/**
* A handler to specify how a transition should be interrupted.
*
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Key.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Key.kt
index a9edf0a..acb436e 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Key.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Key.kt
@@ -64,15 +64,15 @@
}
/** Key for an element. */
-class ElementKey(
+open class ElementKey(
debugName: String,
identity: Any = Object(),
/**
- * The [ElementScenePicker] to use when deciding in which scene we should draw shared Elements
+ * The [ElementContentPicker] to use when deciding in which scene we should draw shared Elements
* or compose MovableElements.
*/
- val scenePicker: ElementScenePicker = DefaultElementScenePicker,
+ open val contentPicker: ElementContentPicker = DefaultElementContentPicker,
) : Key(debugName, identity), ElementMatcher {
@VisibleForTesting
// TODO(b/240432457): Make internal once PlatformComposeSceneTransitionLayoutTestsUtils can
@@ -99,6 +99,33 @@
}
}
+/** Key for a movable element. */
+class MovableElementKey(
+ debugName: String,
+
+ /**
+ * The [StaticElementContentPicker] to use when deciding in which scene we should draw shared
+ * Elements or compose MovableElements.
+ *
+ * @see DefaultElementContentPicker
+ * @see MovableElementContentPicker
+ */
+ override val contentPicker: StaticElementContentPicker,
+ identity: Any = Object(),
+) : ElementKey(debugName, identity, contentPicker) {
+ constructor(
+ debugName: String,
+
+ /** The exhaustive list of contents (scenes or overlays) that can contain this element. */
+ contents: Set<ContentKey>,
+ identity: Any = Object(),
+ ) : this(debugName, MovableElementContentPicker(contents), identity)
+
+ override fun toString(): String {
+ return "MovableElementKey(debugName=$debugName)"
+ }
+}
+
/** Key for a shared value of an element. */
class ValueKey(debugName: String, identity: Any = Object()) : Key(debugName, identity) {
override fun toString(): String {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
index e556f6f..abecdd7 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
@@ -28,6 +28,7 @@
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.util.fastLastOrNull
import com.android.compose.animation.scene.content.Content
+import com.android.compose.animation.scene.content.state.TransitionState
@Composable
internal fun Element(
@@ -53,7 +54,7 @@
internal fun MovableElement(
layoutImpl: SceneTransitionLayoutImpl,
sceneOrOverlay: Content,
- key: ElementKey,
+ key: MovableElementKey,
modifier: Modifier,
content: @Composable ElementScope<MovableElementContentScope>.() -> Unit,
) {
@@ -111,7 +112,7 @@
private class MovableElementScopeImpl(
private val layoutImpl: SceneTransitionLayoutImpl,
- private val element: ElementKey,
+ private val element: MovableElementKey,
private val content: Content,
private val baseContentScope: BaseContentScope,
private val boxScope: BoxScope,
@@ -169,7 +170,7 @@
private fun shouldComposeMovableElement(
layoutImpl: SceneTransitionLayoutImpl,
content: ContentKey,
- element: ElementKey,
+ element: MovableElementKey,
): Boolean {
val transitions = layoutImpl.state.currentTransitions
if (transitions.isEmpty()) {
@@ -181,14 +182,10 @@
// The current transition for this element is the last transition in which either fromScene or
// toScene contains the element.
+ val contents = element.contentPicker.contents
val transition =
transitions.fastLastOrNull { transition ->
- element.scenePicker.sceneDuringTransition(
- element = element,
- transition = transition,
- fromSceneZIndex = layoutImpl.scenes.getValue(transition.fromScene).zIndex,
- toSceneZIndex = layoutImpl.scenes.getValue(transition.toScene).zIndex,
- ) != null
+ transition.fromScene in contents || transition.toScene in contents
} ?: return false
// Always compose movable elements in the scene picked by their scene picker.
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt
index f1b2249..ae5344f 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt
@@ -17,6 +17,7 @@
package com.android.compose.animation.scene
import androidx.compose.runtime.snapshotFlow
+import com.android.compose.animation.scene.content.state.TransitionState
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOf
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/PredictiveBackHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/PredictiveBackHandler.kt
index fd6762b..fe16ef751 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/PredictiveBackHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/PredictiveBackHandler.kt
@@ -25,6 +25,7 @@
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
+import com.android.compose.animation.scene.content.state.TransitionState
import kotlin.coroutines.cancellation.CancellationException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
index 3401af8..65a7367 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
@@ -189,7 +189,7 @@
*/
@Composable
fun MovableElement(
- key: ElementKey,
+ key: MovableElementKey,
modifier: Modifier,
// TODO(b/317026105): As discussed in http://shortn/_gJVdltF8Si, remove the @Composable
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
index 2a739d7..a6c6a80 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
@@ -18,10 +18,6 @@
import android.util.Log
import androidx.annotation.VisibleForTesting
-import androidx.compose.animation.core.Animatable
-import androidx.compose.animation.core.AnimationVector1D
-import androidx.compose.animation.core.spring
-import androidx.compose.foundation.gestures.Orientation
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@@ -29,12 +25,12 @@
import androidx.compose.ui.util.fastAll
import androidx.compose.ui.util.fastFilter
import androidx.compose.ui.util.fastForEach
+import com.android.compose.animation.scene.content.state.ContentState
+import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.animation.scene.transition.link.LinkedTransition
import com.android.compose.animation.scene.transition.link.StateLink
import kotlin.math.absoluteValue
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.launch
/**
* The state of a [SceneTransitionLayout].
@@ -146,212 +142,6 @@
)
}
-@Stable
-sealed interface TransitionState {
- /**
- * The current effective scene. If a new transition was triggered, it would start from this
- * scene.
- *
- * For instance, when swiping from scene A to scene B, the [currentScene] is A when the swipe
- * gesture starts, but then if the user flings their finger and commits the transition to scene
- * B, then [currentScene] becomes scene B even if the transition is not finished yet and is
- * still animating to settle to scene B.
- */
- val currentScene: SceneKey
-
- /** No transition/animation is currently running. */
- data class Idle(override val currentScene: SceneKey) : TransitionState
-
- /** There is a transition animating between two scenes. */
- abstract class Transition(
- /** The scene this transition is starting from. Can't be the same as toScene */
- val fromScene: SceneKey,
-
- /** The scene this transition is going to. Can't be the same as fromScene */
- val toScene: SceneKey,
-
- /** The transition that `this` transition is replacing, if any. */
- internal val replacedTransition: Transition? = null,
- ) : TransitionState {
- /**
- * The key of this transition. This should usually be null, but it can be specified to use a
- * specific set of transformations associated to this transition.
- */
- open val key: TransitionKey? = null
-
- /**
- * The progress of the transition. This is usually in the `[0; 1]` range, but it can also be
- * less than `0` or greater than `1` when using transitions with a spring AnimationSpec or
- * when flinging quickly during a swipe gesture.
- */
- abstract val progress: Float
-
- /** The current velocity of [progress], in progress units. */
- abstract val progressVelocity: Float
-
- /**
- * The progress of the preview transition. This is usually in the `[0; 1]` range, but it can
- * also be less than `0` or greater than `1` when using transitions with a spring
- * AnimationSpec or when flinging quickly during a swipe gesture.
- */
- open val previewProgress: Float = 0f
-
- /** The current velocity of [previewProgress], in progress units. */
- open val previewProgressVelocity: Float = 0f
-
- /** Whether the transition is currently in the preview stage */
- open val isInPreviewStage: Boolean = false
-
- /** Whether the transition was triggered by user input rather than being programmatic. */
- abstract val isInitiatedByUserInput: Boolean
-
- /** Whether user input is currently driving the transition. */
- abstract val isUserInputOngoing: Boolean
-
- /**
- * The current [TransformationSpecImpl] and [OverscrollSpecImpl] associated to this
- * transition.
- *
- * Important: These will be set exactly once, when this transition is
- * [started][MutableSceneTransitionLayoutStateImpl.startTransition].
- */
- internal var transformationSpec: TransformationSpecImpl = TransformationSpec.Empty
- internal var previewTransformationSpec: TransformationSpecImpl? = null
- private var fromOverscrollSpec: OverscrollSpecImpl? = null
- private var toOverscrollSpec: OverscrollSpecImpl? = null
-
- /** The current [OverscrollSpecImpl], if this transition is currently overscrolling. */
- internal val currentOverscrollSpec: OverscrollSpecImpl?
- get() {
- if (this !is HasOverscrollProperties) return null
- val progress = progress
- val bouncingScene = bouncingScene
- return when {
- progress < 0f || bouncingScene == fromScene -> fromOverscrollSpec
- progress > 1f || bouncingScene == toScene -> toOverscrollSpec
- else -> null
- }
- }
-
- /** Returns if the [progress] value of this transition can go beyond range `[0; 1]` */
- fun canOverscroll(): Boolean {
- val overscrollSpec = currentOverscrollSpec ?: return true
- return overscrollSpec.transformationSpec.transformations.isNotEmpty()
- }
-
- /**
- * An animatable that animates from 1f to 0f. This will be used to nicely animate the sudden
- * jump of values when this transitions interrupts another one.
- */
- private var interruptionDecay: Animatable<Float, AnimationVector1D>? = null
-
- init {
- check(fromScene != toScene)
- check(
- replacedTransition == null ||
- (replacedTransition.fromScene == fromScene &&
- replacedTransition.toScene == toScene)
- )
- }
-
- /**
- * Force this transition to finish and animate to [currentScene], so that this transition
- * progress will settle to either 0% (if [currentScene] == [fromScene]) or 100% (if
- * [currentScene] == [toScene]) in a finite amount of time.
- *
- * @return the [Job] that animates the progress to [currentScene]. It can be used to wait
- * until the animation is complete or cancel it to snap to [currentScene]. Calling
- * [finish] multiple times will return the same [Job].
- */
- abstract fun finish(): Job
-
- /**
- * Whether we are transitioning. If [from] or [to] is empty, we will also check that they
- * match the scenes we are animating from and/or to.
- */
- fun isTransitioning(from: SceneKey? = null, to: SceneKey? = null): Boolean {
- return (from == null || fromScene == from) && (to == null || toScene == to)
- }
-
- /** Whether we are transitioning from [scene] to [other], or from [other] to [scene]. */
- fun isTransitioningBetween(scene: SceneKey, other: SceneKey): Boolean {
- return isTransitioning(from = scene, to = other) ||
- isTransitioning(from = other, to = scene)
- }
-
- internal fun updateOverscrollSpecs(
- fromSpec: OverscrollSpecImpl?,
- toSpec: OverscrollSpecImpl?,
- ) {
- fromOverscrollSpec = fromSpec
- toOverscrollSpec = toSpec
- }
-
- internal open fun interruptionProgress(
- layoutImpl: SceneTransitionLayoutImpl,
- ): Float {
- if (!layoutImpl.state.enableInterruptions) {
- return 0f
- }
-
- if (replacedTransition != null) {
- return replacedTransition.interruptionProgress(layoutImpl)
- }
-
- fun create(): Animatable<Float, AnimationVector1D> {
- val animatable = Animatable(1f, visibilityThreshold = ProgressVisibilityThreshold)
- layoutImpl.coroutineScope.launch {
- val swipeSpec = layoutImpl.state.transitions.defaultSwipeSpec
- val progressSpec =
- spring(
- stiffness = swipeSpec.stiffness,
- dampingRatio = swipeSpec.dampingRatio,
- visibilityThreshold = ProgressVisibilityThreshold,
- )
- animatable.animateTo(0f, progressSpec)
- }
-
- return animatable
- }
-
- val animatable = interruptionDecay ?: create().also { interruptionDecay = it }
- return animatable.value
- }
- }
-
- interface HasOverscrollProperties {
- /**
- * The position of the [Transition.toScene].
- *
- * Used to understand the direction of the overscroll.
- */
- val isUpOrLeft: Boolean
-
- /**
- * The relative orientation between [Transition.fromScene] and [Transition.toScene].
- *
- * Used to understand the orientation of the overscroll.
- */
- val orientation: Orientation
-
- /**
- * Scope which can be used in the Overscroll DSL to define a transformation based on the
- * distance between [Transition.fromScene] and [Transition.toScene].
- */
- val overscrollScope: OverscrollScope
-
- /**
- * The scene around which the transition is currently bouncing. When not `null`, this
- * transition is currently oscillating around this scene and will soon settle to that scene.
- */
- val bouncingScene: SceneKey?
-
- companion object {
- const val DistanceUnspecified = 0f
- }
- }
-}
-
/** A [MutableSceneTransitionLayoutState] that holds the value for the current scene. */
internal class MutableSceneTransitionLayoutStateImpl(
initialScene: SceneKey,
@@ -450,7 +240,7 @@
// Compute the [TransformationSpec] when the transition starts.
val fromScene = transition.fromScene
val toScene = transition.toScene
- val orientation = (transition as? TransitionState.HasOverscrollProperties)?.orientation
+ val orientation = (transition as? ContentState.HasOverscrollProperties)?.orientation
// Update the transition specs.
transition.transformationSpec =
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
index cfa4c70..3ded1de 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
@@ -157,16 +157,16 @@
val key: TransitionKey?
/**
- * The scene we are transitioning from. If `null`, this spec can be used to animate from any
- * scene.
+ * The content we are transitioning from. If `null`, this spec can be used to animate from any
+ * content.
*/
- val from: SceneKey?
+ val from: ContentKey?
/**
- * The scene we are transitioning to. If `null`, this spec can be used to animate from any
- * scene.
+ * The content we are transitioning to. If `null`, this spec can be used to animate from any
+ * content.
*/
- val to: SceneKey?
+ val to: ContentKey?
/**
* Return a reversed version of this [TransitionSpec] for a transition going from [to] to
@@ -231,8 +231,8 @@
internal class TransitionSpecImpl(
override val key: TransitionKey?,
- override val from: SceneKey?,
- override val to: SceneKey?,
+ override val from: ContentKey?,
+ override val to: ContentKey?,
private val previewTransformationSpec: (() -> TransformationSpecImpl)? = null,
private val reversePreviewTransformationSpec: (() -> TransformationSpecImpl)? = null,
private val transformationSpec: () -> TransformationSpecImpl
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
index 06be86d..a30b780 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
@@ -23,7 +23,7 @@
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
-import com.android.compose.animation.scene.TransitionState.HasOverscrollProperties.Companion.DistanceUnspecified
+import com.android.compose.animation.scene.content.state.ContentState
/** Define the [transitions][SceneTransitions] to be used with a [SceneTransitionLayout]. */
fun transitions(builder: SceneTransitionsBuilder.() -> Unit): SceneTransitions {
@@ -47,9 +47,9 @@
var interruptionHandler: InterruptionHandler
/**
- * Define the default animation to be played when transitioning [to] the specified scene, from
- * any scene. For the animation specification to apply only when transitioning between two
- * specific scenes, use [from] instead.
+ * Define the default animation to be played when transitioning [to] the specified content, from
+ * any content. For the animation specification to apply only when transitioning between two
+ * specific contents, use [from] instead.
*
* If [key] is not `null`, then this transition will only be used if the same key is specified
* when triggering the transition.
@@ -61,7 +61,7 @@
* @see from
*/
fun to(
- to: SceneKey,
+ to: ContentKey,
key: TransitionKey? = null,
preview: (TransitionBuilder.() -> Unit)? = null,
reversePreview: (TransitionBuilder.() -> Unit)? = null,
@@ -69,12 +69,12 @@
): TransitionSpec
/**
- * Define the animation to be played when transitioning [from] the specified scene. For the
- * animation specification to apply only when transitioning between two specific scenes, pass
- * the destination scene via the [to] argument.
+ * Define the animation to be played when transitioning [from] the specified content. For the
+ * animation specification to apply only when transitioning between two specific contents, pass
+ * the destination content via the [to] argument.
*
- * When looking up which transition should be used when animating from scene A to scene B, we
- * pick the single transition with the given [key] and matching one of these predicates (in
+ * When looking up which transition should be used when animating from content A to content B,
+ * we pick the single transition with the given [key] and matching one of these predicates (in
* order of importance):
* 1. from == A && to == B
* 2. to == A && from == B, which is then treated in reverse.
@@ -86,8 +86,8 @@
* reversible with the reverse animation having a preview as well, define a [reversePreview].
*/
fun from(
- from: SceneKey,
- to: SceneKey? = null,
+ from: ContentKey,
+ to: ContentKey? = null,
key: TransitionKey? = null,
preview: (TransitionBuilder.() -> Unit)? = null,
reversePreview: (TransitionBuilder.() -> Unit)? = null,
@@ -104,8 +104,14 @@
fun overscroll(
scene: SceneKey,
orientation: Orientation,
- builder: OverscrollBuilder.() -> Unit = {},
+ builder: OverscrollBuilder.() -> Unit,
): OverscrollSpec
+
+ /**
+ * Prevents overscroll the [scene] in the given [orientation], allowing ancestors to eventually
+ * consume the remaining gesture.
+ */
+ fun overscrollDisabled(scene: SceneKey, orientation: Orientation): OverscrollSpec
}
interface BaseTransitionBuilder : PropertyTransformationBuilder {
@@ -227,99 +233,176 @@
/**
* An interface to decide where we should draw shared Elements or compose MovableElements.
*
- * @see DefaultElementScenePicker
- * @see HighestZIndexScenePicker
- * @see LowestZIndexScenePicker
- * @see MovableElementScenePicker
+ * @see DefaultElementContentPicker
+ * @see HighestZIndexContentPicker
+ * @see LowestZIndexContentPicker
+ * @see MovableElementContentPicker
*/
-interface ElementScenePicker {
+interface ElementContentPicker {
/**
- * Return the scene in which [element] should be drawn (when using `Modifier.element(key)`) or
+ * Return the content in which [element] should be drawn (when using `Modifier.element(key)`) or
* composed (when using `MovableElement(key)`) during the given [transition]. If this element
- * should not be drawn or composed in neither [transition.fromScene] nor [transition.toScene],
- * return `null`.
+ * should not be drawn or composed in neither [transition.fromContent] nor
+ * [transition.toContent], return `null`.
*
- * Important: For [MovableElements][ContentScope.MovableElement], this scene picker will
+ * Important: For [MovableElements][ContentScope.MovableElement], this content picker will
* *always* be used during transitions to decide whether we should compose that element in a
- * given scene or not. Therefore, you should make sure that the returned [SceneKey] contains the
- * movable element, otherwise that element will not be composed in any scene during the
+ * given content or not. Therefore, you should make sure that the returned [ContentKey] contains
+ * the movable element, otherwise that element will not be composed in any scene during the
* transition.
*/
- fun sceneDuringTransition(
+ fun contentDuringTransition(
element: ElementKey,
- transition: TransitionState.Transition,
- fromSceneZIndex: Float,
- toSceneZIndex: Float,
- ): SceneKey?
+ transition: ContentState.Transition<*>,
+ fromContentZIndex: Float,
+ toContentZIndex: Float,
+ ): ContentKey
/**
- * Return [transition.fromScene] if it is in [scenes] and [transition.toScene] is not, or return
- * [transition.toScene] if it is in [scenes] and [transition.fromScene] is not. If neither
- * [transition.fromScene] and [transition.toScene] are in [scenes], return `null`. If both
- * [transition.fromScene] and [transition.toScene] are in [scenes], throw an exception.
+ * Return [transition.fromContent] if it is in [contents] and [transition.toContent] is not, or
+ * return [transition.toContent] if it is in [contents] and [transition.fromContent] is not. If
+ * neither [transition.toContent] and [transition.fromContent] are in [contents] or if both
+ * [transition.fromContent] and [transition.toContent] are in [contents], throw an exception.
*
- * This function can be useful when computing the scene in which a movable element should be
+ * This function can be useful when computing the content in which a movable element should be
* composed.
*/
- fun pickSingleSceneIn(
- scenes: Set<SceneKey>,
- transition: TransitionState.Transition,
+ fun pickSingleContentIn(
+ contents: Set<ContentKey>,
+ transition: ContentState.Transition<*>,
element: ElementKey,
- ): SceneKey? {
- val fromScene = transition.fromScene
- val toScene = transition.toScene
- val fromSceneInScenes = scenes.contains(fromScene)
- val toSceneInScenes = scenes.contains(toScene)
+ ): ContentKey {
+ val fromContent = transition.fromContent
+ val toContent = transition.toContent
+ val fromContentInContents = contents.contains(fromContent)
+ val toContentInContents = contents.contains(toContent)
- return when {
- fromSceneInScenes && toSceneInScenes -> {
- error(
- "Element $element can be in both $fromScene and $toScene. You should add a " +
- "special case for this transition before calling pickSingleSceneIn()."
- )
- }
- fromSceneInScenes -> fromScene
- toSceneInScenes -> toScene
- else -> null
+ if (fromContentInContents && toContentInContents) {
+ error(
+ "Element $element can be in both $fromContent and $toContent. You should add a " +
+ "special case for this transition before calling pickSingleSceneIn()."
+ )
}
- }
-}
-/** An [ElementScenePicker] that draws/composes elements in the scene with the highest z-order. */
-object HighestZIndexScenePicker : ElementScenePicker {
- override fun sceneDuringTransition(
- element: ElementKey,
- transition: TransitionState.Transition,
- fromSceneZIndex: Float,
- toSceneZIndex: Float
- ): SceneKey {
- return if (fromSceneZIndex > toSceneZIndex) {
- transition.fromScene
- } else {
- transition.toScene
+ if (!fromContentInContents && !toContentInContents) {
+ error(
+ "Element $element can be neither in $fromContent and $toContent. This either " +
+ "means that you should add one of them in the scenes set passed to " +
+ "pickSingleSceneIn(), or there is an internal error and this element was " +
+ "composed when it shouldn't be."
+ )
}
- }
-}
-/** An [ElementScenePicker] that draws/composes elements in the scene with the lowest z-order. */
-object LowestZIndexScenePicker : ElementScenePicker {
- override fun sceneDuringTransition(
- element: ElementKey,
- transition: TransitionState.Transition,
- fromSceneZIndex: Float,
- toSceneZIndex: Float
- ): SceneKey {
- return if (fromSceneZIndex < toSceneZIndex) {
- transition.fromScene
+ return if (fromContentInContents) {
+ fromContent
} else {
- transition.toScene
+ toContent
}
}
}
/**
- * An [ElementScenePicker] that draws/composes elements in the scene we are transitioning to, iff
- * that scene is in [scenes].
+ * An element picker on which we can query the set of contents (scenes or overlays) that contain the
+ * element. This is needed by [MovableElement], that needs to know at composition time on which of
+ * the candidate contents an element should be composed.
+ *
+ * @see DefaultElementContentPicker(contents)
+ * @see HighestZIndexContentPicker(contents)
+ * @see LowestZIndexContentPicker(contents)
+ * @see MovableElementContentPicker
+ */
+interface StaticElementContentPicker : ElementContentPicker {
+ /** The exhaustive lists of contents that contain this element. */
+ val contents: Set<ContentKey>
+}
+
+/**
+ * An [ElementContentPicker] that draws/composes elements in the content with the highest z-order.
+ */
+object HighestZIndexContentPicker : ElementContentPicker {
+ override fun contentDuringTransition(
+ element: ElementKey,
+ transition: ContentState.Transition<*>,
+ fromContentZIndex: Float,
+ toContentZIndex: Float
+ ): ContentKey {
+ return if (fromContentZIndex > toContentZIndex) {
+ transition.fromContent
+ } else {
+ transition.toContent
+ }
+ }
+
+ /**
+ * Return a [StaticElementContentPicker] that behaves like [HighestZIndexContentPicker] and can
+ * be used by [MovableElement].
+ */
+ operator fun invoke(contents: Set<ContentKey>): StaticElementContentPicker {
+ return object : StaticElementContentPicker {
+ override val contents: Set<ContentKey> = contents
+
+ override fun contentDuringTransition(
+ element: ElementKey,
+ transition: ContentState.Transition<*>,
+ fromContentZIndex: Float,
+ toContentZIndex: Float
+ ): ContentKey {
+ return HighestZIndexContentPicker.contentDuringTransition(
+ element,
+ transition,
+ fromContentZIndex,
+ toContentZIndex,
+ )
+ }
+ }
+ }
+}
+
+/**
+ * An [ElementContentPicker] that draws/composes elements in the content with the lowest z-order.
+ */
+object LowestZIndexContentPicker : ElementContentPicker {
+ override fun contentDuringTransition(
+ element: ElementKey,
+ transition: ContentState.Transition<*>,
+ fromContentZIndex: Float,
+ toContentZIndex: Float
+ ): ContentKey {
+ return if (fromContentZIndex < toContentZIndex) {
+ transition.fromContent
+ } else {
+ transition.toContent
+ }
+ }
+
+ /**
+ * Return a [StaticElementContentPicker] that behaves like [LowestZIndexContentPicker] and can
+ * be used by [MovableElement].
+ */
+ operator fun invoke(contents: Set<ContentKey>): StaticElementContentPicker {
+ return object : StaticElementContentPicker {
+ override val contents: Set<ContentKey> = contents
+
+ override fun contentDuringTransition(
+ element: ElementKey,
+ transition: ContentState.Transition<*>,
+ fromContentZIndex: Float,
+ toContentZIndex: Float
+ ): ContentKey {
+ return LowestZIndexContentPicker.contentDuringTransition(
+ element,
+ transition,
+ fromContentZIndex,
+ toContentZIndex,
+ )
+ }
+ }
+ }
+}
+
+/**
+ * An [ElementContentPicker] that draws/composes elements in the content we are transitioning to,
+ * iff that content is in [contents].
*
* This picker can be useful for movable elements whose content size depends on its content (because
* it wraps it) in at least one scene. That way, the target size of the MovableElement will be
@@ -331,23 +414,35 @@
* is not the same as when going from scene B to scene A, so it's not usable in situations where
* z-ordering during the transition matters.
*/
-class MovableElementScenePicker(private val scenes: Set<SceneKey>) : ElementScenePicker {
- override fun sceneDuringTransition(
+class MovableElementContentPicker(
+ override val contents: Set<ContentKey>,
+) : StaticElementContentPicker {
+ override fun contentDuringTransition(
element: ElementKey,
- transition: TransitionState.Transition,
- fromSceneZIndex: Float,
- toSceneZIndex: Float,
- ): SceneKey? {
+ transition: ContentState.Transition<*>,
+ fromContentZIndex: Float,
+ toContentZIndex: Float,
+ ): ContentKey {
return when {
- scenes.contains(transition.toScene) -> transition.toScene
- scenes.contains(transition.fromScene) -> transition.fromScene
- else -> null
+ transition.toContent in contents -> transition.toContent
+ else -> {
+ check(transition.fromContent in contents) {
+ "Neither ${transition.fromContent} nor ${transition.toContent} are in " +
+ "contents. This transition should not have been used for this element."
+ }
+ transition.fromContent
+ }
}
}
}
-/** The default [ElementScenePicker]. */
-val DefaultElementScenePicker = HighestZIndexScenePicker
+/** The default [ElementContentPicker]. */
+val DefaultElementContentPicker = HighestZIndexContentPicker
+
+/** The [DefaultElementContentPicker] that can be used for [MovableElement]s. */
+fun DefaultElementContentPicker(contents: Set<ContentKey>): StaticElementContentPicker {
+ return HighestZIndexContentPicker(contents)
+}
@TransitionDsl
interface PropertyTransformationBuilder {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt
index 02a4362..6515cb8 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt
@@ -60,7 +60,7 @@
val transitionOverscrollSpecs = mutableListOf<OverscrollSpecImpl>()
override fun to(
- to: SceneKey,
+ to: ContentKey,
key: TransitionKey?,
preview: (TransitionBuilder.() -> Unit)?,
reversePreview: (TransitionBuilder.() -> Unit)?,
@@ -70,8 +70,8 @@
}
override fun from(
- from: SceneKey,
- to: SceneKey?,
+ from: ContentKey,
+ to: ContentKey?,
key: TransitionKey?,
preview: (TransitionBuilder.() -> Unit)?,
reversePreview: (TransitionBuilder.() -> Unit)?,
@@ -86,6 +86,22 @@
builder: OverscrollBuilder.() -> Unit
): OverscrollSpec {
val impl = OverscrollBuilderImpl().apply(builder)
+ check(impl.transformations.isNotEmpty()) {
+ "This method does not allow empty transformations. " +
+ "Use overscrollDisabled($scene, $orientation) instead."
+ }
+ return overscrollSpec(scene, orientation, impl)
+ }
+
+ override fun overscrollDisabled(scene: SceneKey, orientation: Orientation): OverscrollSpec {
+ return overscrollSpec(scene, orientation, OverscrollBuilderImpl())
+ }
+
+ private fun overscrollSpec(
+ scene: SceneKey,
+ orientation: Orientation,
+ impl: OverscrollBuilderImpl,
+ ): OverscrollSpec {
val spec =
OverscrollSpecImpl(
scene = scene,
@@ -97,15 +113,15 @@
distance = impl.distance,
transformations = impl.transformations,
),
- progressConverter = impl.progressConverter
+ progressConverter = impl.progressConverter,
)
transitionOverscrollSpecs.add(spec)
return spec
}
private fun transition(
- from: SceneKey?,
- to: SceneKey?,
+ from: ContentKey?,
+ to: ContentKey?,
key: TransitionKey?,
preview: (TransitionBuilder.() -> Unit)?,
reversePreview: (TransitionBuilder.() -> Unit)?,
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt
index 492d211..6f608cb 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt
@@ -39,6 +39,7 @@
import com.android.compose.animation.scene.ElementStateScope
import com.android.compose.animation.scene.MovableElement
import com.android.compose.animation.scene.MovableElementContentScope
+import com.android.compose.animation.scene.MovableElementKey
import com.android.compose.animation.scene.NestedScrollBehavior
import com.android.compose.animation.scene.SceneTransitionLayoutImpl
import com.android.compose.animation.scene.SceneTransitionLayoutState
@@ -130,7 +131,7 @@
@Composable
override fun MovableElement(
- key: ElementKey,
+ key: MovableElementKey,
modifier: Modifier,
content: @Composable (ElementScope<MovableElementContentScope>.() -> Unit)
) {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/ContentState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/ContentState.kt
new file mode 100644
index 0000000..add3934
--- /dev/null
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/ContentState.kt
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compose.animation.scene.content.state
+
+import androidx.compose.animation.core.Animatable
+import androidx.compose.animation.core.AnimationVector1D
+import androidx.compose.animation.core.spring
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.runtime.Stable
+import com.android.compose.animation.scene.ContentKey
+import com.android.compose.animation.scene.OverscrollScope
+import com.android.compose.animation.scene.OverscrollSpecImpl
+import com.android.compose.animation.scene.ProgressVisibilityThreshold
+import com.android.compose.animation.scene.SceneTransitionLayoutImpl
+import com.android.compose.animation.scene.TransformationSpec
+import com.android.compose.animation.scene.TransformationSpecImpl
+import com.android.compose.animation.scene.TransitionKey
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.launch
+
+/** The state associated to one or more contents. */
+@Stable
+sealed interface ContentState<out T : ContentKey> {
+ /** The [content] is idle, it does not animate. */
+ sealed class Idle<T : ContentKey>(val content: T) : ContentState<T>
+
+ /** The content is transitioning with another content. */
+ sealed class Transition<out T : ContentKey>(
+ val fromContent: T,
+ val toContent: T,
+ internal val replacedTransition: Transition<T>?,
+ ) : ContentState<T> {
+ /**
+ * The key of this transition. This should usually be null, but it can be specified to use a
+ * specific set of transformations associated to this transition.
+ */
+ open val key: TransitionKey? = null
+
+ /**
+ * The progress of the transition. This is usually in the `[0; 1]` range, but it can also be
+ * less than `0` or greater than `1` when using transitions with a spring AnimationSpec or
+ * when flinging quickly during a swipe gesture.
+ */
+ abstract val progress: Float
+
+ /** The current velocity of [progress], in progress units. */
+ abstract val progressVelocity: Float
+
+ /** Whether the transition was triggered by user input rather than being programmatic. */
+ abstract val isInitiatedByUserInput: Boolean
+
+ /** Whether user input is currently driving the transition. */
+ abstract val isUserInputOngoing: Boolean
+
+ /**
+ * The progress of the preview transition. This is usually in the `[0; 1]` range, but it can
+ * also be less than `0` or greater than `1` when using transitions with a spring
+ * AnimationSpec or when flinging quickly during a swipe gesture.
+ */
+ internal open val previewProgress: Float = 0f
+
+ /** The current velocity of [previewProgress], in progress units. */
+ internal open val previewProgressVelocity: Float = 0f
+
+ /** Whether the transition is currently in the preview stage */
+ internal open val isInPreviewStage: Boolean = false
+
+ /**
+ * The current [TransformationSpecImpl] and [OverscrollSpecImpl] associated to this
+ * transition.
+ *
+ * Important: These will be set exactly once, when this transition is
+ * [started][MutableSceneTransitionLayoutStateImpl.startTransition].
+ */
+ internal var transformationSpec: TransformationSpecImpl = TransformationSpec.Empty
+ internal var previewTransformationSpec: TransformationSpecImpl? = null
+ private var fromOverscrollSpec: OverscrollSpecImpl? = null
+ private var toOverscrollSpec: OverscrollSpecImpl? = null
+
+ /** The current [OverscrollSpecImpl], if this transition is currently overscrolling. */
+ internal val currentOverscrollSpec: OverscrollSpecImpl?
+ get() {
+ if (this !is HasOverscrollProperties) return null
+ val progress = progress
+ val bouncingContent = bouncingContent
+ return when {
+ progress < 0f || bouncingContent == fromContent -> fromOverscrollSpec
+ progress > 1f || bouncingContent == toContent -> toOverscrollSpec
+ else -> null
+ }
+ }
+
+ /**
+ * An animatable that animates from 1f to 0f. This will be used to nicely animate the sudden
+ * jump of values when this transitions interrupts another one.
+ */
+ private var interruptionDecay: Animatable<Float, AnimationVector1D>? = null
+
+ init {
+ check(fromContent != toContent)
+ check(
+ replacedTransition == null ||
+ (replacedTransition.fromContent == fromContent &&
+ replacedTransition.toContent == toContent)
+ )
+ }
+
+ /**
+ * Force this transition to finish and animate to an [Idle] state.
+ *
+ * Important: Once this is called, the effective state of the transition should remain
+ * unchanged. For instance, in the case of a [TransitionState.Transition], its
+ * [currentScene][TransitionState.Transition.currentScene] should never change once [finish]
+ * is called.
+ *
+ * @return the [Job] that animates to the idle state. It can be used to wait until the
+ * animation is complete or cancel it to snap the animation. Calling [finish] multiple
+ * times will return the same [Job].
+ */
+ abstract fun finish(): Job
+
+ /**
+ * Whether we are transitioning. If [from] or [to] is empty, we will also check that they
+ * match the contents we are animating from and/or to.
+ */
+ fun isTransitioning(from: ContentKey? = null, to: ContentKey? = null): Boolean {
+ return (from == null || fromContent == from) && (to == null || toContent == to)
+ }
+
+ /** Whether we are transitioning from [content] to [other], or from [other] to [content]. */
+ fun isTransitioningBetween(content: ContentKey, other: ContentKey): Boolean {
+ return isTransitioning(from = content, to = other) ||
+ isTransitioning(from = other, to = content)
+ }
+
+ internal fun updateOverscrollSpecs(
+ fromSpec: OverscrollSpecImpl?,
+ toSpec: OverscrollSpecImpl?,
+ ) {
+ fromOverscrollSpec = fromSpec
+ toOverscrollSpec = toSpec
+ }
+
+ /** Returns if the [progress] value of this transition can go beyond range `[0; 1]` */
+ internal fun isWithinProgressRange(progress: Float): Boolean {
+ // If the properties are missing we assume that every [Transition] can overscroll
+ if (this !is HasOverscrollProperties) return true
+ // [OverscrollSpec] for the current scene, even if it hasn't started overscrolling yet.
+ val specForCurrentScene =
+ when {
+ progress <= 0f -> fromOverscrollSpec
+ progress >= 1f -> toOverscrollSpec
+ else -> null
+ } ?: return true
+
+ return specForCurrentScene.transformationSpec.transformations.isNotEmpty()
+ }
+
+ internal open fun interruptionProgress(
+ layoutImpl: SceneTransitionLayoutImpl,
+ ): Float {
+ if (!layoutImpl.state.enableInterruptions) {
+ return 0f
+ }
+
+ if (replacedTransition != null) {
+ return replacedTransition.interruptionProgress(layoutImpl)
+ }
+
+ fun create(): Animatable<Float, AnimationVector1D> {
+ val animatable = Animatable(1f, visibilityThreshold = ProgressVisibilityThreshold)
+ layoutImpl.coroutineScope.launch {
+ val swipeSpec = layoutImpl.state.transitions.defaultSwipeSpec
+ val progressSpec =
+ spring(
+ stiffness = swipeSpec.stiffness,
+ dampingRatio = swipeSpec.dampingRatio,
+ visibilityThreshold = ProgressVisibilityThreshold,
+ )
+ animatable.animateTo(0f, progressSpec)
+ }
+
+ return animatable
+ }
+
+ val animatable = interruptionDecay ?: create().also { interruptionDecay = it }
+ return animatable.value
+ }
+ }
+
+ interface HasOverscrollProperties {
+ /**
+ * The position of the [Transition.toContent].
+ *
+ * Used to understand the direction of the overscroll.
+ */
+ val isUpOrLeft: Boolean
+
+ /**
+ * The relative orientation between [Transition.fromContent] and [Transition.toContent].
+ *
+ * Used to understand the orientation of the overscroll.
+ */
+ val orientation: Orientation
+
+ /**
+ * Scope which can be used in the Overscroll DSL to define a transformation based on the
+ * distance between [Transition.fromContent] and [Transition.toContent].
+ */
+ val overscrollScope: OverscrollScope
+
+ /**
+ * The content (scene or overlay) around which the transition is currently bouncing. When
+ * not `null`, this transition is currently oscillating around this content and will soon
+ * settle to that content.
+ */
+ val bouncingContent: ContentKey?
+
+ companion object {
+ const val DistanceUnspecified = 0f
+ }
+ }
+}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt
new file mode 100644
index 0000000..77de22c
--- /dev/null
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compose.animation.scene.content.state
+
+import androidx.compose.runtime.Stable
+import com.android.compose.animation.scene.SceneKey
+
+/** The state associated to one or more scenes. */
+// TODO(b/353679003): Rename to SceneState.
+@Stable
+sealed interface TransitionState : ContentState<SceneKey> {
+ /**
+ * The current effective scene. If a new transition was triggered, it would start from this
+ * scene.
+ *
+ * For instance, when swiping from scene A to scene B, the [currentScene] is A when the swipe
+ * gesture starts, but then if the user flings their finger and commits the transition to scene
+ * B, then [currentScene] becomes scene B even if the transition is not finished yet and is
+ * still animating to settle to scene B.
+ */
+ val currentScene: SceneKey
+
+ /** The scene [currentScene] is idle. */
+ data class Idle(
+ override val currentScene: SceneKey,
+ ) : TransitionState, ContentState.Idle<SceneKey>(currentScene)
+
+ /** There is a transition animating between [fromScene] and [toScene]. */
+ abstract class Transition(
+ /** The scene this transition is starting from. Can't be the same as toScene */
+ val fromScene: SceneKey,
+
+ /** The scene this transition is going to. Can't be the same as fromScene */
+ val toScene: SceneKey,
+
+ /** The transition that `this` transition is replacing, if any. */
+ replacedTransition: Transition? = null,
+ ) : TransitionState, ContentState.Transition<SceneKey>(fromScene, toScene, replacedTransition)
+}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredSize.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredSize.kt
index 65d4d2d..538ce79 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredSize.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredSize.kt
@@ -21,9 +21,8 @@
import com.android.compose.animation.scene.Element
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.ElementMatcher
-import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.SceneTransitionLayoutImpl
-import com.android.compose.animation.scene.TransitionState
+import com.android.compose.animation.scene.content.state.ContentState
/** Anchor the size of an element to the size of another element. */
internal class AnchoredSize(
@@ -36,19 +35,19 @@
layoutImpl: SceneTransitionLayoutImpl,
content: ContentKey,
element: Element,
- sceneState: Element.State,
- transition: TransitionState.Transition,
+ stateInContent: Element.State,
+ transition: ContentState.Transition<*>,
value: IntSize,
): IntSize {
- fun anchorSizeIn(scene: SceneKey): IntSize {
+ fun anchorSizeIn(content: ContentKey): IntSize {
val size =
- layoutImpl.elements[anchor]?.stateByContent?.get(scene)?.targetSize?.takeIf {
+ layoutImpl.elements[anchor]?.stateByContent?.get(content)?.targetSize?.takeIf {
it != Element.SizeUnspecified
}
?: throwMissingAnchorException(
transformation = "AnchoredSize",
anchor = anchor,
- scene = scene,
+ content = content,
)
return IntSize(
@@ -60,10 +59,10 @@
// This simple implementation assumes that the size of [element] is the same as the size of
// the [anchor] in [scene], so simply transform to the size of the anchor in the other
// scene.
- return if (content == transition.fromScene) {
- anchorSizeIn(transition.toScene)
+ return if (content == transition.fromContent) {
+ anchorSizeIn(transition.toContent)
} else {
- anchorSizeIn(transition.fromScene)
+ anchorSizeIn(transition.fromContent)
}
}
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredTranslate.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredTranslate.kt
index 8d7e1c9..258f541 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredTranslate.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredTranslate.kt
@@ -22,9 +22,8 @@
import com.android.compose.animation.scene.Element
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.ElementMatcher
-import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.SceneTransitionLayoutImpl
-import com.android.compose.animation.scene.TransitionState
+import com.android.compose.animation.scene.content.state.ContentState
/** Anchor the translation of an element to another element. */
internal class AnchoredTranslate(
@@ -35,33 +34,33 @@
layoutImpl: SceneTransitionLayoutImpl,
content: ContentKey,
element: Element,
- sceneState: Element.State,
- transition: TransitionState.Transition,
+ stateInContent: Element.State,
+ transition: ContentState.Transition<*>,
value: Offset,
): Offset {
- fun throwException(scene: SceneKey?): Nothing {
+ fun throwException(content: ContentKey?): Nothing {
throwMissingAnchorException(
transformation = "AnchoredTranslate",
anchor = anchor,
- scene = scene,
+ content = content,
)
}
- val anchor = layoutImpl.elements[anchor] ?: throwException(scene = null)
- fun anchorOffsetIn(scene: SceneKey): Offset? {
- return anchor.stateByContent[scene]?.targetOffset?.takeIf { it.isSpecified }
+ val anchor = layoutImpl.elements[anchor] ?: throwException(content = null)
+ fun anchorOffsetIn(content: ContentKey): Offset? {
+ return anchor.stateByContent[content]?.targetOffset?.takeIf { it.isSpecified }
}
// [element] will move the same amount as [anchor] does.
// TODO(b/290184746): Also support anchors that are not shared but translated because of
// other transformations, like an edge translation.
val anchorFromOffset =
- anchorOffsetIn(transition.fromScene) ?: throwException(transition.fromScene)
+ anchorOffsetIn(transition.fromContent) ?: throwException(transition.fromContent)
val anchorToOffset =
- anchorOffsetIn(transition.toScene) ?: throwException(transition.toScene)
+ anchorOffsetIn(transition.toContent) ?: throwException(transition.toContent)
val offset = anchorToOffset - anchorFromOffset
- return if (content == transition.toScene) {
+ return if (content == transition.toContent) {
Offset(
value.x - offset.x,
value.y - offset.y,
@@ -78,11 +77,11 @@
internal fun throwMissingAnchorException(
transformation: String,
anchor: ElementKey,
- scene: SceneKey?,
+ content: ContentKey?,
): Nothing {
error(
"""
- Anchor ${anchor.debugName} does not have a target state in scene ${scene?.debugName}.
+ Anchor ${anchor.debugName} does not have a target state in content ${content?.debugName}.
This either means that it was not composed at all during the transition or that it was
composed too late, for instance during layout/subcomposition. To avoid flickers in
$transformation, you should make sure that the composition and layout of anchor is *not*
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/DrawScale.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/DrawScale.kt
index f010c3b..be8dac21 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/DrawScale.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/DrawScale.kt
@@ -22,7 +22,7 @@
import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.Scale
import com.android.compose.animation.scene.SceneTransitionLayoutImpl
-import com.android.compose.animation.scene.TransitionState
+import com.android.compose.animation.scene.content.state.ContentState
/**
* Scales the draw size of an element. Note this will only scale the draw inside of an element,
@@ -39,8 +39,8 @@
layoutImpl: SceneTransitionLayoutImpl,
content: ContentKey,
element: Element,
- sceneState: Element.State,
- transition: TransitionState.Transition,
+ stateInContent: Element.State,
+ transition: ContentState.Transition<*>,
value: Scale,
): Scale {
return Scale(scaleX, scaleY, pivot)
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/EdgeTranslate.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/EdgeTranslate.kt
index dfce997..d72e43a 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/EdgeTranslate.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/EdgeTranslate.kt
@@ -22,7 +22,7 @@
import com.android.compose.animation.scene.Element
import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.SceneTransitionLayoutImpl
-import com.android.compose.animation.scene.TransitionState
+import com.android.compose.animation.scene.content.state.ContentState
/** Translate an element from an edge of the layout. */
internal class EdgeTranslate(
@@ -34,12 +34,12 @@
layoutImpl: SceneTransitionLayoutImpl,
content: ContentKey,
element: Element,
- sceneState: Element.State,
- transition: TransitionState.Transition,
+ stateInContent: Element.State,
+ transition: ContentState.Transition<*>,
value: Offset
): Offset {
val sceneSize = layoutImpl.content(content).targetSize
- val elementSize = sceneState.targetSize
+ val elementSize = stateInContent.targetSize
if (elementSize == Element.SizeUnspecified) {
return value
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Fade.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Fade.kt
index c1bb017..92ae30f8 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Fade.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Fade.kt
@@ -20,7 +20,7 @@
import com.android.compose.animation.scene.Element
import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.SceneTransitionLayoutImpl
-import com.android.compose.animation.scene.TransitionState
+import com.android.compose.animation.scene.content.state.ContentState
/** Fade an element in or out. */
internal class Fade(
@@ -30,8 +30,8 @@
layoutImpl: SceneTransitionLayoutImpl,
content: ContentKey,
element: Element,
- sceneState: Element.State,
- transition: TransitionState.Transition,
+ stateInContent: Element.State,
+ transition: ContentState.Transition<*>,
value: Float
): Float {
// Return the alpha value of [element] either when it starts fading in or when it finished
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/ScaleSize.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/ScaleSize.kt
index 5adbf7e..e8515dc 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/ScaleSize.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/ScaleSize.kt
@@ -21,7 +21,7 @@
import com.android.compose.animation.scene.Element
import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.SceneTransitionLayoutImpl
-import com.android.compose.animation.scene.TransitionState
+import com.android.compose.animation.scene.content.state.ContentState
import kotlin.math.roundToInt
/**
@@ -37,8 +37,8 @@
layoutImpl: SceneTransitionLayoutImpl,
content: ContentKey,
element: Element,
- sceneState: Element.State,
- transition: TransitionState.Transition,
+ stateInContent: Element.State,
+ transition: ContentState.Transition<*>,
value: IntSize,
): IntSize {
return IntSize(
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt
index 24b7194..77ec891 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt
@@ -23,7 +23,7 @@
import com.android.compose.animation.scene.Element
import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.SceneTransitionLayoutImpl
-import com.android.compose.animation.scene.TransitionState
+import com.android.compose.animation.scene.content.state.ContentState
/** A transformation applied to one or more elements during a transition. */
sealed interface Transformation {
@@ -63,8 +63,8 @@
layoutImpl: SceneTransitionLayoutImpl,
content: ContentKey,
element: Element,
- sceneState: Element.State,
- transition: TransitionState.Transition,
+ stateInContent: Element.State,
+ transition: ContentState.Transition<*>,
value: T,
): T
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Translate.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Translate.kt
index 123756a..fab4ced 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Translate.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Translate.kt
@@ -24,7 +24,7 @@
import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.OverscrollScope
import com.android.compose.animation.scene.SceneTransitionLayoutImpl
-import com.android.compose.animation.scene.TransitionState
+import com.android.compose.animation.scene.content.state.ContentState
internal class Translate(
override val matcher: ElementMatcher,
@@ -35,8 +35,8 @@
layoutImpl: SceneTransitionLayoutImpl,
content: ContentKey,
element: Element,
- sceneState: Element.State,
- transition: TransitionState.Transition,
+ stateInContent: Element.State,
+ transition: ContentState.Transition<*>,
value: Offset,
): Offset {
return with(layoutImpl.density) {
@@ -57,14 +57,14 @@
layoutImpl: SceneTransitionLayoutImpl,
content: ContentKey,
element: Element,
- sceneState: Element.State,
- transition: TransitionState.Transition,
+ stateInContent: Element.State,
+ transition: ContentState.Transition<*>,
value: Offset,
): Offset {
// As this object is created by OverscrollBuilderImpl and we retrieve the current
// OverscrollSpec only when the transition implements HasOverscrollProperties, we can assume
// that this method was invoked after performing this check.
- val overscrollProperties = transition as TransitionState.HasOverscrollProperties
+ val overscrollProperties = transition as ContentState.HasOverscrollProperties
return Offset(
x = value.x + overscrollProperties.overscrollScope.x(),
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/LinkedTransition.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/LinkedTransition.kt
index ed98885..23bcf10 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/LinkedTransition.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/LinkedTransition.kt
@@ -18,7 +18,7 @@
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.TransitionKey
-import com.android.compose.animation.scene.TransitionState
+import com.android.compose.animation.scene.content.state.TransitionState
import kotlinx.coroutines.Job
/** A linked transition which is driven by a [originalTransition]. */
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/StateLink.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/StateLink.kt
index 2018d6e..c0c40dd 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/StateLink.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/StateLink.kt
@@ -20,7 +20,7 @@
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.SceneTransitionLayoutState
import com.android.compose.animation.scene.TransitionKey
-import com.android.compose.animation.scene.TransitionState
+import com.android.compose.animation.scene.content.state.TransitionState
/** A link between a source (implicit) and [target] `SceneTransitionLayoutState`. */
class StateLink(target: SceneTransitionLayoutState, val transitionLinks: List<TransitionLink>) {
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt
index 0f33303..01895c9 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt
@@ -88,11 +88,11 @@
@Composable
private fun ContentScope.MovableFoo(
+ key: MovableElementKey,
targetValues: Values,
onCurrentValueChanged: (Values) -> Unit,
) {
- val key = TestElements.Foo
- MovableElement(key = key, Modifier) {
+ MovableElement(key, Modifier) {
val int by animateElementIntAsState(targetValues.int, key = TestValues.Value1)
val float by animateElementFloatAsState(targetValues.float, key = TestValues.Value2)
val dp by animateElementDpAsState(targetValues.dp, key = TestValues.Value3)
@@ -183,15 +183,22 @@
var lastValueInFrom = fromValues
var lastValueInTo = toValues
+ val key = MovableElementKey("Foo", contents = setOf(SceneA, SceneB))
+
rule.testTransition(
fromSceneContent = {
MovableFoo(
+ key = key,
targetValues = fromValues,
- onCurrentValueChanged = { lastValueInFrom = it }
+ onCurrentValueChanged = { lastValueInFrom = it },
)
},
toSceneContent = {
- MovableFoo(targetValues = toValues, onCurrentValueChanged = { lastValueInTo = it })
+ MovableFoo(
+ key = key,
+ targetValues = toValues,
+ onCurrentValueChanged = { lastValueInTo = it },
+ )
},
transition = {
// The transition lasts 64ms = 4 frames.
@@ -453,7 +460,7 @@
rule.runOnUiThread {
MutableSceneTransitionLayoutStateImpl(
SceneA,
- transitions { overscroll(SceneB, Orientation.Horizontal) }
+ transitions { overscrollDisabled(SceneB, Orientation.Horizontal) }
)
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
index c8bbb14..dc5b2f7 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
@@ -35,7 +35,8 @@
import com.android.compose.animation.scene.TestScenes.SceneA
import com.android.compose.animation.scene.TestScenes.SceneB
import com.android.compose.animation.scene.TestScenes.SceneC
-import com.android.compose.animation.scene.TransitionState.Transition
+import com.android.compose.animation.scene.content.state.TransitionState
+import com.android.compose.animation.scene.content.state.TransitionState.Transition
import com.android.compose.animation.scene.subjects.assertThat
import com.android.compose.test.MonotonicClockTestScope
import com.android.compose.test.runMonotonicClockTest
@@ -195,10 +196,17 @@
startedPosition: Offset = Offset.Zero,
overSlop: Float,
pointersDown: Int = 1,
+ expectedConsumedOverSlop: Float = overSlop,
): DragController {
// overSlop should be 0f only if the drag gesture starts with startDragImmediately
if (overSlop == 0f) error("Consider using onDragStartedImmediately()")
- return onDragStarted(draggableHandler, startedPosition, overSlop, pointersDown)
+ return onDragStarted(
+ draggableHandler = draggableHandler,
+ startedPosition = startedPosition,
+ overSlop = overSlop,
+ pointersDown = pointersDown,
+ expectedConsumedOverSlop = expectedConsumedOverSlop,
+ )
}
fun onDragStartedImmediately(
@@ -213,7 +221,7 @@
startedPosition: Offset = Offset.Zero,
overSlop: Float = 0f,
pointersDown: Int = 1,
- expectedConsumed: Boolean = true,
+ expectedConsumedOverSlop: Float = overSlop,
): DragController {
val dragController =
draggableHandler.onDragStarted(
@@ -223,14 +231,14 @@
)
// MultiPointerDraggable will always call onDelta with the initial overSlop right after
- dragController.onDragDelta(pixels = overSlop, expectedConsumed = expectedConsumed)
+ dragController.onDragDelta(pixels = overSlop, expectedConsumedOverSlop)
return dragController
}
- fun DragController.onDragDelta(pixels: Float, expectedConsumed: Boolean = true) {
+ fun DragController.onDragDelta(pixels: Float, expectedConsumed: Float = pixels) {
val consumed = onDrag(delta = pixels)
- assertThat(consumed).isEqualTo(if (expectedConsumed) pixels else 0f)
+ assertThat(consumed).isEqualTo(expectedConsumed)
}
fun DragController.onDragStopped(
@@ -370,14 +378,14 @@
onDragStarted(
horizontalDraggableHandler,
overSlop = up(fractionOfScreen = 0.3f),
- expectedConsumed = false,
+ expectedConsumedOverSlop = 0f,
)
assertIdle(currentScene = SceneA)
onDragStarted(
horizontalDraggableHandler,
overSlop = down(fractionOfScreen = 0.3f),
- expectedConsumed = false,
+ expectedConsumedOverSlop = 0f,
)
assertIdle(currentScene = SceneA)
}
@@ -504,19 +512,19 @@
// start accelaratedScroll and scroll over to B -> null
val dragController2 = onDragStartedImmediately()
- dragController2.onDragDelta(pixels = up(fractionOfScreen = 0.5f), expectedConsumed = false)
- dragController2.onDragDelta(pixels = up(fractionOfScreen = 0.5f), expectedConsumed = false)
+ dragController2.onDragDelta(pixels = up(fractionOfScreen = 0.5f), expectedConsumed = 0f)
+ dragController2.onDragDelta(pixels = up(fractionOfScreen = 0.5f), expectedConsumed = 0f)
// here onDragStopped is already triggered, but subsequent onDelta/onDragStopped calls may
// still be called. Make sure that they don't crash or change the scene
- dragController2.onDragDelta(pixels = up(fractionOfScreen = 0.5f), expectedConsumed = false)
+ dragController2.onDragDelta(pixels = up(fractionOfScreen = 0.5f), expectedConsumed = 0f)
dragController2.onDragStopped(velocity = 0f)
advanceUntilIdle()
assertIdle(SceneB)
// These events can still come in after the animation has settled
- dragController2.onDragDelta(pixels = up(fractionOfScreen = 0.5f), expectedConsumed = false)
+ dragController2.onDragDelta(pixels = up(fractionOfScreen = 0.5f), expectedConsumed = 0f)
dragController2.onDragStopped(velocity = 0f)
assertIdle(SceneB)
}
@@ -1047,12 +1055,20 @@
@Test
fun emptyOverscrollImmediatelyAbortsSettleAnimationWhenOverProgress() = runGestureTest {
// Overscrolling on scene B does nothing.
- layoutState.transitions = transitions { overscroll(SceneB, Orientation.Vertical) {} }
+ layoutState.transitions = transitions { overscrollDisabled(SceneB, Orientation.Vertical) }
// Swipe up to scene B at progress = 200%.
val middle = Offset(SCREEN_SIZE / 2f, SCREEN_SIZE / 2f)
- val dragController = onDragStarted(startedPosition = middle, overSlop = up(2f))
- val transition = assertTransition(fromScene = SceneA, toScene = SceneB, progress = 2f)
+ val dragController =
+ onDragStarted(
+ startedPosition = middle,
+ overSlop = up(2f),
+ // Overscroll is disabled, it will scroll up to 100%
+ expectedConsumedOverSlop = up(1f),
+ )
+
+ // The progress value is coerced in `[0..1]`
+ assertTransition(fromScene = SceneA, toScene = SceneB, progress = 1f)
// Release the finger.
dragController.onDragStopped(velocity = -velocityThreshold)
@@ -1061,9 +1077,6 @@
// 100% and that the overscroll on scene B is doing nothing, we are already idle.
runCurrent()
assertIdle(SceneB)
-
- // Progress is snapped to 100%.
- assertThat(transition).hasProgress(1f)
}
@Test
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementScenePickerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementContentPickerTest.kt
similarity index 93%
rename from packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementScenePickerTest.kt
rename to packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementContentPickerTest.kt
index 3b022e8..96e521b 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementScenePickerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementContentPickerTest.kt
@@ -31,12 +31,12 @@
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
-class ElementScenePickerTest {
+class ElementContentPickerTest {
@get:Rule val rule = createComposeRule()
@Test
fun highestZIndexPicker() {
- val key = ElementKey("TestElement", scenePicker = HighestZIndexScenePicker)
+ val key = ElementKey("TestElement", contentPicker = HighestZIndexContentPicker)
rule.testTransition(
fromSceneContent = { Box(Modifier.element(key).size(10.dp)) },
toSceneContent = { Box(Modifier.element(key).size(10.dp)) },
@@ -62,7 +62,7 @@
@Test
fun lowestZIndexPicker() {
- val key = ElementKey("TestElement", scenePicker = LowestZIndexScenePicker)
+ val key = ElementKey("TestElement", contentPicker = LowestZIndexContentPicker)
rule.testTransition(
fromSceneContent = { Box(Modifier.element(key).size(10.dp)) },
toSceneContent = { Box(Modifier.element(key).size(10.dp)) },
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
index 329257e..75f44ff 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
@@ -1513,7 +1513,7 @@
rule.runOnUiThread {
MutableSceneTransitionLayoutStateImpl(
SceneA,
- transitions { overscroll(SceneA, Orientation.Horizontal) {} }
+ transitions { overscrollDisabled(SceneA, Orientation.Horizontal) }
)
.apply {
startTransition(
@@ -1666,8 +1666,8 @@
MutableSceneTransitionLayoutStateImpl(
SceneA,
transitions {
- overscroll(SceneA, Orientation.Horizontal)
- overscroll(SceneB, Orientation.Horizontal)
+ overscrollDisabled(SceneA, Orientation.Horizontal)
+ overscrollDisabled(SceneB, Orientation.Horizontal)
}
)
}
@@ -1714,8 +1714,8 @@
MutableSceneTransitionLayoutStateImpl(
SceneA,
transitions {
- overscroll(SceneA, Orientation.Horizontal)
- overscroll(SceneB, Orientation.Horizontal)
+ overscrollDisabled(SceneA, Orientation.Horizontal)
+ overscrollDisabled(SceneB, Orientation.Horizontal)
}
)
}
@@ -1723,9 +1723,11 @@
val fooInA = "fooInA"
val fooInB = "fooInB"
+ val key = MovableElementKey("Foo", contents = setOf(SceneA, SceneB))
+
@Composable
fun ContentScope.MovableFoo(text: String, modifier: Modifier = Modifier) {
- MovableElement(TestElements.Foo, modifier) { content { Text(text) } }
+ MovableElement(key, modifier) { content { Text(text) } }
}
rule.setContent {
@@ -2036,7 +2038,7 @@
rule.runOnIdle {
MutableSceneTransitionLayoutStateImpl(
SceneA,
- transitions { overscroll(SceneA, Orientation.Horizontal) }
+ transitions { overscrollDisabled(SceneA, Orientation.Horizontal) }
)
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/InterruptionHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/InterruptionHandlerTest.kt
index 3552d3d..ca72181 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/InterruptionHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/InterruptionHandlerTest.kt
@@ -22,6 +22,7 @@
import com.android.compose.animation.scene.TestScenes.SceneA
import com.android.compose.animation.scene.TestScenes.SceneB
import com.android.compose.animation.scene.TestScenes.SceneC
+import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.animation.scene.subjects.assertThat
import com.android.compose.test.runMonotonicClockTest
import com.google.common.truth.Correspondence
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementScenePickerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementContentPickerTest.kt
similarity index 60%
rename from packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementScenePickerTest.kt
rename to packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementContentPickerTest.kt
index 6745fbe..e1d0945 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementScenePickerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementContentPickerTest.kt
@@ -18,20 +18,22 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertThrows
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
-class MovableElementScenePickerTest {
+class MovableElementContentPickerTest {
@Test
fun toSceneInScenes() {
- val picker = MovableElementScenePicker(scenes = setOf(TestScenes.SceneA, TestScenes.SceneB))
+ val picker =
+ MovableElementContentPicker(contents = setOf(TestScenes.SceneA, TestScenes.SceneB))
assertThat(
- picker.sceneDuringTransition(
+ picker.contentDuringTransition(
TestElements.Foo,
transition(from = TestScenes.SceneA, to = TestScenes.SceneB),
- fromSceneZIndex = 0f,
- toSceneZIndex = 1f,
+ fromContentZIndex = 0f,
+ toContentZIndex = 1f,
)
)
.isEqualTo(TestScenes.SceneB)
@@ -39,13 +41,13 @@
@Test
fun fromSceneInScenes() {
- val picker = MovableElementScenePicker(scenes = setOf(TestScenes.SceneA))
+ val picker = MovableElementContentPicker(contents = setOf(TestScenes.SceneA))
assertThat(
- picker.sceneDuringTransition(
+ picker.contentDuringTransition(
TestElements.Foo,
transition(from = TestScenes.SceneA, to = TestScenes.SceneB),
- fromSceneZIndex = 0f,
- toSceneZIndex = 1f,
+ fromContentZIndex = 0f,
+ toContentZIndex = 1f,
)
)
.isEqualTo(TestScenes.SceneA)
@@ -53,15 +55,14 @@
@Test
fun noneInScenes() {
- val picker = MovableElementScenePicker(scenes = emptySet())
- assertThat(
- picker.sceneDuringTransition(
- TestElements.Foo,
- transition(from = TestScenes.SceneA, to = TestScenes.SceneB),
- fromSceneZIndex = 0f,
- toSceneZIndex = 1f,
- )
+ val picker = MovableElementContentPicker(contents = emptySet())
+ assertThrows(IllegalStateException::class.java) {
+ picker.contentDuringTransition(
+ TestElements.Foo,
+ transition(from = TestScenes.SceneA, to = TestScenes.SceneB),
+ fromContentZIndex = 0f,
+ toContentZIndex = 1f,
)
- .isEqualTo(null)
+ }
}
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt
index 821cc29..520e759 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt
@@ -43,6 +43,10 @@
import androidx.compose.ui.test.performClick
import androidx.compose.ui.unit.dp
import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.compose.animation.scene.TestScenes.SceneA
+import com.android.compose.animation.scene.TestScenes.SceneB
+import com.android.compose.animation.scene.content.state.ContentState
+import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.animation.scene.subjects.assertThat
import com.android.compose.test.assertSizeIsEqualTo
import com.google.common.truth.Truth.assertThat
@@ -62,7 +66,7 @@
}
@Composable
- private fun ContentScope.MovableCounter(key: ElementKey, modifier: Modifier) {
+ private fun ContentScope.MovableCounter(key: MovableElementKey, modifier: Modifier) {
MovableElement(key, modifier) { content { Counter() } }
}
@@ -74,8 +78,8 @@
},
toSceneContent = { Box(Modifier.element(TestElements.Foo).size(100.dp)) { Counter() } },
transition = { spec = tween(durationMillis = 16 * 4, easing = LinearEasing) },
- fromScene = TestScenes.SceneA,
- toScene = TestScenes.SceneB,
+ fromScene = SceneA,
+ toScene = SceneB,
) {
before {
// Click 3 times on the counter.
@@ -103,7 +107,7 @@
rule
.onNode(
hasText("count: 3") and
- hasParent(isElement(TestElements.Foo, scene = TestScenes.SceneA))
+ hasParent(isElement(TestElements.Foo, scene = SceneA))
)
.assertExists()
.assertIsNotDisplayed()
@@ -111,7 +115,7 @@
rule
.onNode(
hasText("count: 0") and
- hasParent(isElement(TestElements.Foo, scene = TestScenes.SceneB))
+ hasParent(isElement(TestElements.Foo, scene = SceneB))
)
.assertIsDisplayed()
.assertSizeIsEqualTo(75.dp, 75.dp)
@@ -148,27 +152,30 @@
@Test
fun movableElementIsMovedAndComposedOnlyOnce() {
val key =
- ElementKey(
+ MovableElementKey(
"Foo",
- scenePicker =
- object : ElementScenePicker {
- override fun sceneDuringTransition(
+ contentPicker =
+ object : StaticElementContentPicker {
+ override val contents: Set<ContentKey> = setOf(SceneA, SceneB)
+
+ override fun contentDuringTransition(
element: ElementKey,
- transition: TransitionState.Transition,
- fromSceneZIndex: Float,
- toSceneZIndex: Float
- ): SceneKey {
- assertThat(transition).hasFromScene(TestScenes.SceneA)
- assertThat(transition).hasToScene(TestScenes.SceneB)
- assertThat(fromSceneZIndex).isEqualTo(0)
- assertThat(toSceneZIndex).isEqualTo(1)
+ transition: ContentState.Transition<*>,
+ fromContentZIndex: Float,
+ toContentZIndex: Float
+ ): ContentKey {
+ transition as TransitionState.Transition
+ assertThat(transition).hasFromScene(SceneA)
+ assertThat(transition).hasToScene(SceneB)
+ assertThat(fromContentZIndex).isEqualTo(0)
+ assertThat(toContentZIndex).isEqualTo(1)
// Compose Foo in Scene A if progress < 0.65f, otherwise compose it
// in Scene B.
return if (transition.progress < 0.65f) {
- TestScenes.SceneA
+ SceneA
} else {
- TestScenes.SceneB
+ SceneB
}
}
}
@@ -178,8 +185,8 @@
fromSceneContent = { MovableCounter(key, Modifier.size(50.dp)) },
toSceneContent = { MovableCounter(key, Modifier.size(100.dp)) },
transition = { spec = tween(durationMillis = 16 * 4, easing = LinearEasing) },
- fromScene = TestScenes.SceneA,
- toScene = TestScenes.SceneB,
+ fromScene = SceneA,
+ toScene = SceneB,
) {
before {
// Click 3 times on the counter.
@@ -207,7 +214,7 @@
rule
.onNode(
hasText("count: 3") and
- hasParent(isElement(TestElements.Foo, scene = TestScenes.SceneA))
+ hasParent(isElement(TestElements.Foo, scene = SceneA))
)
.assertIsDisplayed()
.assertSizeIsEqualTo(75.dp, 75.dp)
@@ -228,7 +235,7 @@
rule
.onNode(
hasText("count: 3") and
- hasParent(isElement(TestElements.Foo, scene = TestScenes.SceneB))
+ hasParent(isElement(TestElements.Foo, scene = SceneB))
)
.assertIsDisplayed()
@@ -263,17 +270,19 @@
@Test
fun movableElementContentIsRecomposedIfContentParametersChange() {
+ val key = MovableElementKey("Foo", contents = setOf(SceneA, SceneB))
+
@Composable
fun ContentScope.MovableFoo(text: String, modifier: Modifier = Modifier) {
- MovableElement(TestElements.Foo, modifier) { content { Text(text) } }
+ MovableElement(key, modifier) { content { Text(text) } }
}
rule.testTransition(
fromSceneContent = { MovableFoo(text = "fromScene") },
toSceneContent = { MovableFoo(text = "toScene") },
transition = { spec = tween(durationMillis = 16 * 4, easing = LinearEasing) },
- fromScene = TestScenes.SceneA,
- toScene = TestScenes.SceneB,
+ fromScene = SceneA,
+ toScene = SceneB,
) {
// Before the transition, only fromScene is composed.
before {
@@ -314,9 +323,10 @@
@Test
fun movableElementScopeExtendsBoxScope() {
+ val key = MovableElementKey("Foo", contents = setOf(SceneA))
rule.setContent {
TestContentScope {
- MovableElement(TestElements.Foo, Modifier.size(200.dp)) {
+ MovableElement(key, Modifier.size(200.dp)) {
content {
Box(Modifier.testTag("bottomEnd").align(Alignment.BottomEnd))
Box(Modifier.testTag("matchParentSize").matchParentSize())
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
index 52cceec..6b417ee 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
@@ -25,6 +25,7 @@
import com.android.compose.animation.scene.TestScenes.SceneB
import com.android.compose.animation.scene.TestScenes.SceneC
import com.android.compose.animation.scene.TestScenes.SceneD
+import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.animation.scene.subjects.assertThat
import com.android.compose.animation.scene.transition.link.StateLink
import com.android.compose.test.runMonotonicClockTest
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
index 32f3bac..84bcc28f 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
@@ -322,7 +322,7 @@
rule.runOnUiThread {
MutableSceneTransitionLayoutStateImpl(
SceneA,
- transitions { overscroll(SceneB, Orientation.Horizontal) }
+ transitions { overscrollDisabled(SceneB, Orientation.Horizontal) }
)
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
index 0766e00..04a9380 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
@@ -29,6 +29,9 @@
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
+import androidx.compose.ui.input.nestedscroll.NestedScrollSource
+import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.LocalViewConfiguration
import androidx.compose.ui.platform.testTag
@@ -786,4 +789,61 @@
.onNode(isElement(SceneB.rootElementKey))
.assertPositionInRootIsEqualTo(-layoutSize, 0.dp)
}
+
+ @Test
+ fun whenOverscrollIsDisabled_dragGestureShouldNotBeConsumed() {
+ val swipeDistance = 100.dp
+
+ var availableOnPostScroll = Float.MIN_VALUE
+ val connection =
+ object : NestedScrollConnection {
+ override fun onPostScroll(
+ consumed: Offset,
+ available: Offset,
+ source: NestedScrollSource
+ ): Offset {
+ availableOnPostScroll = available.y
+ return super.onPostScroll(consumed, available, source)
+ }
+ }
+ val state =
+ rule.runOnUiThread {
+ MutableSceneTransitionLayoutState(
+ SceneA,
+ transitions {
+ from(SceneA, to = SceneB) { distance = FixedDistance(swipeDistance) }
+ overscrollDisabled(SceneB, Orientation.Vertical)
+ }
+ )
+ }
+ val layoutSize = 200.dp
+ var touchSlop = 0f
+ rule.setContent {
+ touchSlop = LocalViewConfiguration.current.touchSlop
+ SceneTransitionLayout(state, Modifier.size(layoutSize).nestedScroll(connection)) {
+ scene(SceneA, userActions = mapOf(Swipe.Down to SceneB)) {
+ Box(Modifier.fillMaxSize())
+ }
+ scene(SceneB) { Box(Modifier.element(TestElements.Foo).fillMaxSize()) }
+ }
+ }
+
+ // Swipe down by the swipe distance so that we are on scene B.
+ rule.onRoot().performTouchInput {
+ val middle = (layoutSize / 2).toPx()
+ down(Offset(middle, middle))
+ moveBy(Offset(0f, touchSlop + (swipeDistance).toPx()), delayMillis = 1_000)
+ }
+ val transition = state.currentTransition
+ assertThat(transition).isNotNull()
+ assertThat(transition!!.progress).isEqualTo(1f)
+ assertThat(availableOnPostScroll).isEqualTo(0f)
+
+ // Overscrolling on Scene B
+ val ovescrollPx = 100f
+ rule.onRoot().performTouchInput { moveBy(Offset(0f, ovescrollPx), delayMillis = 1_000) }
+ // Overscroll is disabled on Scene B
+ assertThat(transition.progress).isEqualTo(1f)
+ assertThat(availableOnPostScroll).isEqualTo(ovescrollPx)
+ }
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/Transition.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/Transition.kt
index 66d4059..91bd7e1 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/Transition.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/Transition.kt
@@ -17,6 +17,8 @@
package com.android.compose.animation.scene
import androidx.compose.foundation.gestures.Orientation
+import com.android.compose.animation.scene.content.state.ContentState
+import com.android.compose.animation.scene.content.state.TransitionState
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
@@ -37,14 +39,14 @@
isInitiatedByUserInput: Boolean = false,
isUserInputOngoing: Boolean = false,
isUpOrLeft: Boolean = false,
- bouncingScene: SceneKey? = null,
+ bouncingContent: ContentKey? = null,
orientation: Orientation = Orientation.Horizontal,
onFinish: ((TransitionState.Transition) -> Job)? = null,
replacedTransition: TransitionState.Transition? = null,
): TransitionState.Transition {
return object :
TransitionState.Transition(from, to, replacedTransition),
- TransitionState.HasOverscrollProperties {
+ ContentState.HasOverscrollProperties {
override val currentScene: SceneKey
get() = current()
@@ -66,7 +68,7 @@
override val isInitiatedByUserInput: Boolean = isInitiatedByUserInput
override val isUserInputOngoing: Boolean = isUserInputOngoing
override val isUpOrLeft: Boolean = isUpOrLeft
- override val bouncingScene: SceneKey? = bouncingScene
+ override val bouncingContent: ContentKey? = bouncingContent
override val orientation: Orientation = orientation
override val overscrollScope: OverscrollScope =
object : OverscrollScope {
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/TransitionDslTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/TransitionDslTest.kt
index a3790f8..68240b5 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/TransitionDslTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/TransitionDslTest.kt
@@ -27,6 +27,7 @@
import com.android.compose.animation.scene.transformation.TransformationRange
import com.google.common.truth.Correspondence
import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertThrows
import org.junit.Test
import org.junit.runner.RunWith
@@ -58,7 +59,7 @@
assertThat(transitions.transitionSpecs)
.comparingElementsUsing(
- Correspondence.transforming<TransitionSpecImpl, Pair<SceneKey?, SceneKey?>>(
+ Correspondence.transforming<TransitionSpecImpl, Pair<ContentKey?, ContentKey?>>(
{ it?.from to it?.to },
"has (from, to) equal to"
)
@@ -252,6 +253,22 @@
assertThat(transformation).isInstanceOf(OverscrollTranslate::class.java)
}
+ @Test
+ fun overscrollSpec_for_overscrollDisabled() {
+ val transitions = transitions {
+ overscrollDisabled(TestScenes.SceneA, Orientation.Vertical)
+ }
+ val overscrollSpec = transitions.overscrollSpecs.single()
+ assertThat(overscrollSpec.transformationSpec.transformations).isEmpty()
+ }
+
+ @Test
+ fun overscrollSpec_throwIfTransformationsIsEmpty() {
+ assertThrows(IllegalStateException::class.java) {
+ transitions { overscroll(TestScenes.SceneA, Orientation.Vertical) {} }
+ }
+ }
+
companion object {
private val TRANSFORMATION_RANGE =
Correspondence.transforming<Transformation, TransformationRange?>(
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/subjects/TransitionStateSubject.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/subjects/TransitionStateSubject.kt
index e997a75..a12ab78 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/subjects/TransitionStateSubject.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/subjects/TransitionStateSubject.kt
@@ -18,7 +18,8 @@
import com.android.compose.animation.scene.OverscrollSpec
import com.android.compose.animation.scene.SceneKey
-import com.android.compose.animation.scene.TransitionState
+import com.android.compose.animation.scene.content.state.ContentState
+import com.android.compose.animation.scene.content.state.TransitionState
import com.google.common.truth.Fact.simpleFact
import com.google.common.truth.FailureMetadata
import com.google.common.truth.Subject
@@ -132,12 +133,12 @@
}
fun hasBouncingScene(scene: SceneKey) {
- if (actual !is TransitionState.HasOverscrollProperties) {
- failWithActual(simpleFact("expected to be TransitionState.HasOverscrollProperties"))
+ if (actual !is ContentState.HasOverscrollProperties) {
+ failWithActual(simpleFact("expected to be ContentState.HasOverscrollProperties"))
}
- check("bouncingScene")
- .that((actual as TransitionState.HasOverscrollProperties).bouncingScene)
+ check("bouncingContent")
+ .that((actual as ContentState.HasOverscrollProperties).bouncingContent)
.isEqualTo(scene)
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepository.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepository.kt
index 5eca5b4..362e23d 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepository.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepository.kt
@@ -17,6 +17,7 @@
package com.android.systemui.shared.notifications.data.repository
import android.provider.Settings
+import android.provider.Settings.Secure.ZEN_DURATION_PROMPT
import com.android.systemui.shared.settings.data.repository.SecureSettingsRepository
import com.android.systemui.shared.settings.data.repository.SystemSettingsRepository
import kotlinx.coroutines.CoroutineDispatcher
@@ -32,10 +33,10 @@
/** Provides access to state related to notification settings. */
class NotificationSettingsRepository(
- private val scope: CoroutineScope,
+ private val backgroundScope: CoroutineScope,
private val backgroundDispatcher: CoroutineDispatcher,
private val secureSettingsRepository: SecureSettingsRepository,
- private val systemSettingsRepository: SystemSettingsRepository,
+ systemSettingsRepository: SystemSettingsRepository,
) {
val isNotificationHistoryEnabled: Flow<Boolean> =
secureSettingsRepository
@@ -51,9 +52,7 @@
)
.map { it == 1 }
.flowOn(backgroundDispatcher)
- .stateIn(
- scope = scope,
- )
+ .stateIn(scope = backgroundScope)
suspend fun setShowNotificationsOnLockscreenEnabled(enabled: Boolean) {
withContext(backgroundDispatcher) {
@@ -70,8 +69,20 @@
.map { it == 1 }
.flowOn(backgroundDispatcher)
.stateIn(
- scope = scope,
+ scope = backgroundScope,
started = SharingStarted.Eagerly,
initialValue = false,
)
+
+ /** The default duration for DND mode when enabled. See [Settings.Secure.ZEN_DURATION]. */
+ val zenDuration: StateFlow<Int> =
+ secureSettingsRepository
+ .intSetting(name = Settings.Secure.ZEN_DURATION)
+ .distinctUntilChanged()
+ .flowOn(backgroundDispatcher)
+ .stateIn(
+ backgroundScope,
+ started = SharingStarted.Eagerly,
+ initialValue = ZEN_DURATION_PROMPT,
+ )
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
index 6c3f3c1..f7f69d3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
@@ -105,6 +105,7 @@
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
+import org.mockito.Mockito.reset
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -183,7 +184,7 @@
whenever(view.context).thenReturn(mContext)
whenever(view.resources).thenReturn(testableResources.resources)
- val lp = FrameLayout.LayoutParams(/* width= */ 0, /* height= */ 0)
+ val lp = FrameLayout.LayoutParams(/* width= */ 0, /* height= */ 0)
lp.gravity = 0
whenever(view.layoutParams).thenReturn(lp)
@@ -542,6 +543,7 @@
// THEN the next security method of None will dismiss keyguard.
verify(viewMediatorCallback, never()).keyguardDone(anyInt())
}
+
@Test
fun showNextSecurityScreenOrFinish_SimPin_Swipe_userNotSetup() {
// GIVEN the current security method is SimPin
@@ -635,14 +637,6 @@
verify(configurationController).addCallback(configurationListenerArgumentCaptor.capture())
clearInvocations(viewFlipperController)
configurationListenerArgumentCaptor.value.onDensityOrFontScaleChanged()
- verify(viewFlipperController).clearViews()
- verify(viewFlipperController)
- .asynchronouslyInflateView(
- eq(SecurityMode.PIN),
- any(),
- onViewInflatedCallbackArgumentCaptor.capture()
- )
- onViewInflatedCallbackArgumentCaptor.value.onViewInflated(inputViewController)
verify(view).onDensityOrFontScaleChanged()
}
@@ -771,7 +765,9 @@
underTest.reinflateViewFlipper(onViewInflatedCallback)
verify(viewFlipperController).clearViews()
verify(viewFlipperController)
- .asynchronouslyInflateView(any(), any(), eq(onViewInflatedCallback))
+ .asynchronouslyInflateView(any(), any(), onViewInflatedCallbackArgumentCaptor.capture())
+ onViewInflatedCallbackArgumentCaptor.value.onViewInflated(inputViewController)
+ verify(view).updateSecurityViewFlipper()
}
@Test
@@ -935,8 +931,10 @@
underTest.onViewAttached()
verify(userSwitcherController)
.addUserSwitchCallback(capture(userSwitchCallbackArgumentCaptor))
+ reset(primaryBouncerInteractor)
userSwitchCallbackArgumentCaptor.value.onUserSwitched()
- verify(viewFlipperController).asynchronouslyInflateView(any(), any(), any())
+
+ verify(primaryBouncerInteractor).setLastShownPrimarySecurityScreen(any())
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt
index 4fd44cc..cfe0bec 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt
@@ -35,6 +35,7 @@
import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
import com.android.systemui.bouncer.shared.model.BouncerMessageModel
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryBiometricsAllowedInteractor
import com.android.systemui.deviceentry.domain.interactor.deviceEntryFingerprintAuthInteractor
import com.android.systemui.flags.SystemPropertiesHelper
import com.android.systemui.keyguard.data.repository.fakeBiometricSettingsRepository
@@ -108,7 +109,9 @@
facePropertyRepository = kosmos.fakeFacePropertyRepository,
deviceEntryFingerprintAuthInteractor = kosmos.deviceEntryFingerprintAuthInteractor,
faceAuthRepository = kosmos.fakeDeviceEntryFaceAuthRepository,
- securityModel = securityModel
+ securityModel = securityModel,
+ deviceEntryBiometricsAllowedInteractor =
+ kosmos.deviceEntryBiometricsAllowedInteractor,
)
biometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(
fingerprintAuthCurrentlyAllowed
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/smartspace/SmartspaceInteractionHandlerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/smartspace/SmartspaceInteractionHandlerTest.kt
index d51d356..15c57d8 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/smartspace/SmartspaceInteractionHandlerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/smartspace/SmartspaceInteractionHandlerTest.kt
@@ -31,6 +31,7 @@
import com.android.systemui.communal.widgets.SmartspaceAppWidgetHostView
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testScope
+import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.testKosmos
import kotlinx.coroutines.test.runTest
@@ -55,7 +56,7 @@
private val testIntent =
PendingIntent.getActivity(
context,
- /* requestCode = */ 0,
+ /* requestCode= */ 0,
Intent("action"),
PendingIntent.FLAG_IMMUTABLE
)
@@ -66,7 +67,12 @@
@Before
fun setUp() {
with(kosmos) {
- underTest = SmartspaceInteractionHandler(activityStarter, communalSceneInteractor)
+ underTest =
+ SmartspaceInteractionHandler(
+ activityStarter = activityStarter,
+ communalSceneInteractor = communalSceneInteractor,
+ logBuffer = logcatLogBuffer(),
+ )
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
index 7a41bc6..1255248 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
@@ -99,7 +99,9 @@
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
+import org.mockito.kotlin.never
import org.mockito.kotlin.spy
+import org.mockito.kotlin.times
import org.mockito.kotlin.whenever
import platform.test.runner.parameterized.ParameterizedAndroidJunit4
import platform.test.runner.parameterized.Parameters
@@ -741,6 +743,18 @@
}
@Test
+ fun communalContent_readTriggersUmoVisibilityUpdate() =
+ testScope.runTest {
+ verify(mediaHost, never()).updateViewVisibility()
+
+ val communalContent by collectLastValue(underTest.communalContent)
+
+ // updateViewVisibility is called when the flow is collected.
+ assertThat(communalContent).isNotNull()
+ verify(mediaHost).updateViewVisibility()
+ }
+
+ @Test
fun scrollPosition_persistedOnEditEntry() {
val index = 2
val offset = 30
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt
index ea8b5ab..023de52 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt
@@ -29,6 +29,7 @@
import com.android.systemui.communal.domain.interactor.communalSceneInteractor
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testScope
+import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.testKosmos
import kotlinx.coroutines.test.runTest
@@ -53,7 +54,7 @@
private val testIntent =
PendingIntent.getActivity(
context,
- /* requestCode = */ 0,
+ /* requestCode= */ 0,
Intent("action"),
PendingIntent.FLAG_IMMUTABLE
)
@@ -64,7 +65,12 @@
@Before
fun setUp() {
with(kosmos) {
- underTest = WidgetInteractionHandler(activityStarter, communalSceneInteractor)
+ underTest =
+ WidgetInteractionHandler(
+ activityStarter = activityStarter,
+ communalSceneInteractor = communalSceneInteractor,
+ logBuffer = logcatLogBuffer(),
+ )
}
}
@@ -76,7 +82,7 @@
assertFalse(launching!!)
val parent = FrameLayout(context)
- val view = CommunalAppWidgetHostView(context)
+ val view = CommunalAppWidgetHostView(context, underTest)
parent.addView(view)
val (fillInIntent, activityOptions) = testResponse.getLaunchOptions(view)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFingerprintAuthInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFingerprintAuthInteractorTest.kt
index 51f9957..605d125 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFingerprintAuthInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFingerprintAuthInteractorTest.kt
@@ -21,8 +21,6 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.deviceEntryFingerprintAuthRepository
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
@@ -36,41 +34,29 @@
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
private val underTest = kosmos.deviceEntryFingerprintAuthInteractor
- private val fingerprintAuthRepository = kosmos.deviceEntryFingerprintAuthRepository
private val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository
- private val biometricSettingsRepository = kosmos.biometricSettingsRepository
@Test
- fun isFingerprintAuthCurrentlyAllowed_allowedOnlyWhenItIsNotLockedOutAndAllowedBySettings() =
+ fun isSensorUnderDisplay() =
testScope.runTest {
- val currentlyAllowed by collectLastValue(underTest.isFingerprintAuthCurrentlyAllowed)
- biometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(true)
- fingerprintAuthRepository.setLockedOut(true)
-
- assertThat(currentlyAllowed).isFalse()
-
- fingerprintAuthRepository.setLockedOut(false)
- assertThat(currentlyAllowed).isTrue()
-
- biometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(false)
- assertThat(currentlyAllowed).isFalse()
+ val isUdfps by collectLastValue(underTest.isSensorUnderDisplay)
+ fingerprintPropertyRepository.supportsUdfps()
+ assertThat(isUdfps).isTrue()
}
@Test
- fun isFingerprintCurrentlyAllowedInBouncer_trueForNonUdfpsSensorTypes() =
+ fun isSensorUnderDisplay_rear() =
testScope.runTest {
- biometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(true)
-
- val isFingerprintCurrentlyAllowedInBouncer by
- collectLastValue(underTest.isFingerprintCurrentlyAllowedOnBouncer)
-
- fingerprintPropertyRepository.supportsUdfps()
- assertThat(isFingerprintCurrentlyAllowedInBouncer).isFalse()
-
+ val isUdfps by collectLastValue(underTest.isSensorUnderDisplay)
fingerprintPropertyRepository.supportsRearFps()
- assertThat(isFingerprintCurrentlyAllowedInBouncer).isTrue()
+ assertThat(isUdfps).isFalse()
+ }
+ @Test
+ fun isSensorUnderDisplay_side() =
+ testScope.runTest {
+ val isUdfps by collectLastValue(underTest.isSensorUnderDisplay)
fingerprintPropertyRepository.supportsSideFps()
- assertThat(isFingerprintCurrentlyAllowedInBouncer).isTrue()
+ assertThat(isUdfps).isFalse()
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/data/repository/ContextualEducationRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/data/repository/ContextualEducationRepositoryTest.kt
index 3a4b14b..331db52 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/data/repository/ContextualEducationRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/data/repository/ContextualEducationRepositoryTest.kt
@@ -22,10 +22,10 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestableContext
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.contextualeducation.GestureType.BACK
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
-import com.android.systemui.shared.education.GestureType.BACK_GESTURE
import com.google.common.truth.Truth.assertThat
import java.io.File
import java.time.Clock
@@ -70,8 +70,8 @@
fun changeRetrievedValueForNewUser() =
testScope.runTest {
// Update data for old user.
- underTest.incrementSignalCount(BACK_GESTURE)
- val model by collectLastValue(underTest.readGestureEduModelFlow(BACK_GESTURE))
+ underTest.incrementSignalCount(BACK)
+ val model by collectLastValue(underTest.readGestureEduModelFlow(BACK))
assertThat(model?.signalCount).isEqualTo(1)
// User is changed.
@@ -83,17 +83,17 @@
@Test
fun incrementSignalCount() =
testScope.runTest {
- underTest.incrementSignalCount(BACK_GESTURE)
- val model by collectLastValue(underTest.readGestureEduModelFlow(BACK_GESTURE))
+ underTest.incrementSignalCount(BACK)
+ val model by collectLastValue(underTest.readGestureEduModelFlow(BACK))
assertThat(model?.signalCount).isEqualTo(1)
}
@Test
fun dataAddedOnUpdateShortcutTriggerTime() =
testScope.runTest {
- val model by collectLastValue(underTest.readGestureEduModelFlow(BACK_GESTURE))
+ val model by collectLastValue(underTest.readGestureEduModelFlow(BACK))
assertThat(model?.lastShortcutTriggeredTime).isNull()
- underTest.updateShortcutTriggerTime(BACK_GESTURE)
+ underTest.updateShortcutTriggerTime(BACK)
assertThat(model?.lastShortcutTriggeredTime).isEqualTo(clock.instant())
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
index 01dbc6b..ae3302c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
@@ -20,10 +20,10 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.contextualeducation.GestureType
+import com.android.systemui.contextualeducation.GestureType.BACK
import com.android.systemui.education.data.repository.contextualEducationRepository
import com.android.systemui.kosmos.testScope
-import com.android.systemui.shared.education.GestureType
-import com.android.systemui.shared.education.GestureType.BACK_GESTURE
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runTest
@@ -47,15 +47,15 @@
@Test
fun newEducationInfoOnMaxSignalCountReached() =
testScope.runTest {
- tryTriggeringEducation(BACK_GESTURE)
+ tryTriggeringEducation(BACK)
val model by collectLastValue(underTest.educationTriggered)
- assertThat(model?.gestureType).isEqualTo(BACK_GESTURE)
+ assertThat(model?.gestureType).isEqualTo(BACK)
}
@Test
fun noEducationInfoBeforeMaxSignalCountReached() =
testScope.runTest {
- repository.incrementSignalCount(BACK_GESTURE)
+ repository.incrementSignalCount(BACK)
val model by collectLastValue(underTest.educationTriggered)
assertThat(model).isNull()
}
@@ -64,8 +64,8 @@
fun noEducationInfoWhenShortcutTriggeredPreviously() =
testScope.runTest {
val model by collectLastValue(underTest.educationTriggered)
- repository.updateShortcutTriggerTime(BACK_GESTURE)
- tryTriggeringEducation(BACK_GESTURE)
+ repository.updateShortcutTriggerTime(BACK)
+ tryTriggeringEducation(BACK)
assertThat(model).isNull()
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadStatsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadStatsInteractorTest.kt
index ee51e37..cd0c58f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadStatsInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadStatsInteractorTest.kt
@@ -20,10 +20,10 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.contextualeducation.GestureType.BACK
import com.android.systemui.education.data.repository.contextualEducationRepository
import com.android.systemui.education.data.repository.fakeEduClock
import com.android.systemui.kosmos.testScope
-import com.android.systemui.shared.education.GestureType.BACK_GESTURE
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runTest
@@ -41,11 +41,9 @@
fun dataUpdatedOnIncrementSignalCount() =
testScope.runTest {
val model by
- collectLastValue(
- kosmos.contextualEducationRepository.readGestureEduModelFlow(BACK_GESTURE)
- )
+ collectLastValue(kosmos.contextualEducationRepository.readGestureEduModelFlow(BACK))
val originalValue = model!!.signalCount
- underTest.incrementSignalCount(BACK_GESTURE)
+ underTest.incrementSignalCount(BACK)
assertThat(model?.signalCount).isEqualTo(originalValue + 1)
}
@@ -53,11 +51,9 @@
fun dataAddedOnUpdateShortcutTriggerTime() =
testScope.runTest {
val model by
- collectLastValue(
- kosmos.contextualEducationRepository.readGestureEduModelFlow(BACK_GESTURE)
- )
+ collectLastValue(kosmos.contextualEducationRepository.readGestureEduModelFlow(BACK))
assertThat(model?.lastShortcutTriggeredTime).isNull()
- underTest.updateShortcutTriggerTime(BACK_GESTURE)
+ underTest.updateShortcutTriggerTime(BACK)
assertThat(model?.lastShortcutTriggeredTime).isEqualTo(kosmos.fakeEduClock.instant())
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
index a8eccc5..03647b9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
@@ -136,30 +136,6 @@
}
@Test
- fun finishedKeyguardTransitionStepTests() =
- testScope.runTest {
- val finishedSteps by collectValues(underTest.finishedKeyguardTransitionStep)
- val steps = mutableListOf<TransitionStep>()
-
- steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED))
- steps.add(TransitionStep(LOCKSCREEN, AOD, 0.9f, RUNNING))
- steps.add(TransitionStep(LOCKSCREEN, AOD, 1f, FINISHED))
- steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED))
- steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING))
- steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED))
- steps.add(TransitionStep(AOD, GONE, 1f, STARTED))
-
- steps.forEach {
- repository.sendTransitionStep(it)
- runCurrent()
- }
-
- // Ignore the default state.
- assertThat(finishedSteps.subList(1, finishedSteps.size))
- .isEqualTo(listOf(steps[2], steps[5]))
- }
-
- @Test
fun startedKeyguardTransitionStepTests() =
testScope.runTest {
val startedSteps by collectValues(underTest.startedKeyguardTransitionStep)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModelTest.kt
index cde703b..5e9badc 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModelTest.kt
@@ -156,6 +156,43 @@
assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(1f)
}
+ @Test
+ fun deviceEntryBackgroundView_onCancel() =
+ testScope.runTest {
+ fingerprintPropertyRepository.supportsUdfps()
+ val deviceEntryBackgroundViewAlpha by
+ collectLastValue(underTest.deviceEntryBackgroundViewAlpha)
+ runCurrent()
+
+ // GIVEN transition START
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(0f)
+
+ // WHEN transition is cancelled
+ repository.sendTransitionStep(step(.1f, TransitionState.CANCELED))
+
+ // THEN alpha is immediately set to 1f (expected lockscreen alpha state)
+ assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(1f)
+ }
+
+ @Test
+ fun deviceEntryParentViewAlpha_onCancel() =
+ testScope.runTest {
+ fingerprintPropertyRepository.supportsUdfps()
+ val deviceEntryBackgroundViewAlpha by
+ collectLastValue(underTest.deviceEntryParentViewAlpha)
+ runCurrent()
+
+ // GIVEN transition START
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+
+ // WHEN transition is cancelled
+ repository.sendTransitionStep(step(.1f, TransitionState.CANCELED))
+
+ // THEN alpha is immediately set to 1f (expected lockscreen alpha state)
+ assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(1f)
+ }
+
private fun step(
value: Float,
state: TransitionState = TransitionState.RUNNING
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
index 194f362..6dbe94b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
@@ -19,11 +19,13 @@
package com.android.systemui.keyguard.ui.viewmodel
+import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import android.view.View
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
-import com.android.systemui.Flags as AConfigFlags
+import com.android.systemui.Flags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR
+import com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT
import com.android.systemui.Flags.FLAG_NEW_AOD_TRANSITION
import com.android.systemui.SysuiTestCase
import com.android.systemui.communal.data.repository.communalSceneRepository
@@ -68,6 +70,11 @@
@SmallTest
@RunWith(ParameterizedAndroidJunit4::class)
+@EnableFlags(
+ FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT,
+ FLAG_NEW_AOD_TRANSITION,
+ FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR
+)
class KeyguardRootViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
@@ -102,13 +109,6 @@
@Before
fun setUp() {
- mSetFlagsRule.enableFlags(FLAG_NEW_AOD_TRANSITION)
- if (!SceneContainerFlag.isEnabled) {
- mSetFlagsRule.enableFlags(AConfigFlags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR)
- mSetFlagsRule.disableFlags(
- AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT,
- )
- }
kosmos.sceneContainerRepository.setTransitionState(transitionState)
}
@@ -212,6 +212,11 @@
testScope.runTest {
val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
runCurrent()
+ keyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.DOZING,
+ testScope,
+ )
notificationsKeyguardInteractor.setPulseExpanding(false)
deviceEntryRepository.setBypassEnabled(false)
whenever(dozeParameters.alwaysOn).thenReturn(false)
@@ -227,6 +232,11 @@
testScope.runTest {
val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
runCurrent()
+ keyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.DOZING,
+ testScope,
+ )
notificationsKeyguardInteractor.setPulseExpanding(false)
deviceEntryRepository.setBypassEnabled(false)
whenever(dozeParameters.alwaysOn).thenReturn(true)
@@ -243,6 +253,11 @@
testScope.runTest {
val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
runCurrent()
+ keyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.DOZING,
+ testScope,
+ )
notificationsKeyguardInteractor.setPulseExpanding(false)
deviceEntryRepository.setBypassEnabled(false)
whenever(dozeParameters.alwaysOn).thenReturn(true)
@@ -255,6 +270,27 @@
}
@Test
+ fun iconContainer_isNotVisible_bypassDisabled_onLockscreen() =
+ testScope.runTest {
+ val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
+ runCurrent()
+ keyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.AOD,
+ to = KeyguardState.LOCKSCREEN,
+ testScope,
+ )
+ notificationsKeyguardInteractor.setPulseExpanding(false)
+ deviceEntryRepository.setBypassEnabled(false)
+ whenever(dozeParameters.alwaysOn).thenReturn(true)
+ whenever(dozeParameters.displayNeedsBlanking).thenReturn(false)
+ notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
+ runCurrent()
+
+ assertThat(isVisible?.value).isFalse()
+ assertThat(isVisible?.isAnimating).isTrue()
+ }
+
+ @Test
fun isIconContainerVisible_stopAnimation() =
testScope.runTest {
val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
index 6ce7e88..e6ea64f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
@@ -201,6 +201,24 @@
assertThat(actual).isEqualTo(0f)
}
+ @Test
+ fun deviceEntryParentViewAlpha_shadeNotExpanded_onCancel() =
+ testScope.runTest {
+ val actual by collectLastValue(underTest.deviceEntryParentViewAlpha)
+ shadeExpanded(false)
+ runCurrent()
+
+ // START transition
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertThat(actual).isEqualTo(1f)
+
+ // WHEN transition is canceled
+ repository.sendTransitionStep(step(1f, TransitionState.CANCELED))
+
+ // THEN alpha is immediately set to 0f
+ assertThat(actual).isEqualTo(0f)
+ }
+
private fun step(
value: Float,
state: TransitionState = TransitionState.RUNNING,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/ActivatableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/ActivatableTest.kt
new file mode 100644
index 0000000..67517a2
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/ActivatableTest.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.lifecycle
+
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ActivatableTest : SysuiTestCase() {
+
+ @get:Rule val composeRule = createComposeRule()
+
+ @Test
+ fun rememberActivated() {
+ val keepAliveMutable = mutableStateOf(true)
+ var isActive = false
+ composeRule.setContent {
+ val keepAlive by keepAliveMutable
+ if (keepAlive) {
+ rememberActivated {
+ FakeActivatable(
+ onActivation = { isActive = true },
+ onDeactivation = { isActive = false },
+ )
+ }
+ }
+ }
+ assertThat(isActive).isTrue()
+ }
+
+ @Test
+ fun rememberActivated_leavingTheComposition() {
+ val keepAliveMutable = mutableStateOf(true)
+ var isActive = false
+ composeRule.setContent {
+ val keepAlive by keepAliveMutable
+ if (keepAlive) {
+ rememberActivated {
+ FakeActivatable(
+ onActivation = { isActive = true },
+ onDeactivation = { isActive = false },
+ )
+ }
+ }
+ }
+
+ // Tear down the composable.
+ composeRule.runOnUiThread { keepAliveMutable.value = false }
+ composeRule.waitForIdle()
+
+ assertThat(isActive).isFalse()
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/SafeActivatableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/SafeActivatableTest.kt
new file mode 100644
index 0000000..9484821
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/SafeActivatableTest.kt
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.lifecycle
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class SafeActivatableTest : SysuiTestCase() {
+
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+
+ private val underTest = FakeActivatable()
+
+ @Test
+ fun activate() =
+ testScope.runTest {
+ assertThat(underTest.isActive).isFalse()
+ assertThat(underTest.activationCount).isEqualTo(0)
+ assertThat(underTest.cancellationCount).isEqualTo(0)
+
+ underTest.activateIn(testScope)
+ runCurrent()
+ assertThat(underTest.isActive).isTrue()
+ assertThat(underTest.activationCount).isEqualTo(1)
+ assertThat(underTest.cancellationCount).isEqualTo(0)
+ }
+
+ @Test
+ fun activate_andCancel() =
+ testScope.runTest {
+ assertThat(underTest.isActive).isFalse()
+ assertThat(underTest.activationCount).isEqualTo(0)
+ assertThat(underTest.cancellationCount).isEqualTo(0)
+
+ val job = Job()
+ underTest.activateIn(testScope, context = job)
+ runCurrent()
+ assertThat(underTest.isActive).isTrue()
+ assertThat(underTest.activationCount).isEqualTo(1)
+ assertThat(underTest.cancellationCount).isEqualTo(0)
+
+ job.cancel()
+ runCurrent()
+ assertThat(underTest.isActive).isFalse()
+ assertThat(underTest.activationCount).isEqualTo(1)
+ assertThat(underTest.cancellationCount).isEqualTo(1)
+ }
+
+ @Test
+ fun activate_afterCancellation() =
+ testScope.runTest {
+ assertThat(underTest.isActive).isFalse()
+ assertThat(underTest.activationCount).isEqualTo(0)
+ assertThat(underTest.cancellationCount).isEqualTo(0)
+
+ val job = Job()
+ underTest.activateIn(testScope, context = job)
+ runCurrent()
+ assertThat(underTest.isActive).isTrue()
+ assertThat(underTest.activationCount).isEqualTo(1)
+ assertThat(underTest.cancellationCount).isEqualTo(0)
+
+ job.cancel()
+ runCurrent()
+ assertThat(underTest.isActive).isFalse()
+ assertThat(underTest.activationCount).isEqualTo(1)
+ assertThat(underTest.cancellationCount).isEqualTo(1)
+
+ underTest.activateIn(testScope)
+ runCurrent()
+ assertThat(underTest.isActive).isTrue()
+ assertThat(underTest.activationCount).isEqualTo(2)
+ assertThat(underTest.cancellationCount).isEqualTo(1)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun activate_whileActive_throws() =
+ testScope.runTest {
+ assertThat(underTest.isActive).isFalse()
+ assertThat(underTest.activationCount).isEqualTo(0)
+ assertThat(underTest.cancellationCount).isEqualTo(0)
+
+ underTest.activateIn(testScope)
+ runCurrent()
+ assertThat(underTest.isActive).isTrue()
+ assertThat(underTest.activationCount).isEqualTo(1)
+ assertThat(underTest.cancellationCount).isEqualTo(0)
+
+ underTest.activateIn(testScope)
+ runCurrent()
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/SysUiViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/SysUiViewModelTest.kt
new file mode 100644
index 0000000..d1f908d
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/SysUiViewModelTest.kt
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.lifecycle
+
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class SysUiViewModelTest : SysuiTestCase() {
+
+ @get:Rule val composeRule = createComposeRule()
+
+ @Test
+ fun rememberActivated() {
+ val keepAliveMutable = mutableStateOf(true)
+ var isActive = false
+ composeRule.setContent {
+ val keepAlive by keepAliveMutable
+ if (keepAlive) {
+ rememberViewModel {
+ FakeSysUiViewModel(
+ onActivation = { isActive = true },
+ onDeactivation = { isActive = false },
+ )
+ }
+ }
+ }
+ assertThat(isActive).isTrue()
+ }
+
+ @Test
+ fun rememberActivated_withKey() {
+ val keyMutable = mutableStateOf(1)
+ var isActive1 = false
+ var isActive2 = false
+ composeRule.setContent {
+ val key by keyMutable
+ rememberViewModel(key) {
+ when (key) {
+ 1 ->
+ FakeSysUiViewModel(
+ onActivation = { isActive1 = true },
+ onDeactivation = { isActive1 = false },
+ )
+ 2 ->
+ FakeSysUiViewModel(
+ onActivation = { isActive2 = true },
+ onDeactivation = { isActive2 = false },
+ )
+ else -> error("unsupported key $key")
+ }
+ }
+ }
+ assertThat(isActive1).isTrue()
+ assertThat(isActive2).isFalse()
+
+ composeRule.runOnUiThread { keyMutable.value = 2 }
+ composeRule.waitForIdle()
+ assertThat(isActive1).isFalse()
+ assertThat(isActive2).isTrue()
+
+ composeRule.runOnUiThread { keyMutable.value = 1 }
+ composeRule.waitForIdle()
+ assertThat(isActive1).isTrue()
+ assertThat(isActive2).isFalse()
+ }
+
+ @Test
+ fun rememberActivated_leavingTheComposition() {
+ val keepAliveMutable = mutableStateOf(true)
+ var isActive = false
+ composeRule.setContent {
+ val keepAlive by keepAliveMutable
+ if (keepAlive) {
+ rememberViewModel {
+ FakeSysUiViewModel(
+ onActivation = { isActive = true },
+ onDeactivation = { isActive = false },
+ )
+ }
+ }
+ }
+
+ // Tear down the composable.
+ composeRule.runOnUiThread { keepAliveMutable.value = false }
+ composeRule.waitForIdle()
+
+ assertThat(isActive).isFalse()
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt
index 09580c5..d472d98 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt
@@ -24,9 +24,11 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.domain.interactor.displayStateInteractor
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.display.data.repository.displayStateRepository
import com.android.systemui.dump.DumpManager
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testCase
@@ -117,6 +119,7 @@
}
private val shadeInteractor = kosmos.shadeInteractor
+ private val displayStateInteractor = kosmos.displayStateInteractor
private val dumpManager = mock<DumpManager>()
private val underTest =
@@ -124,6 +127,7 @@
qsSceneComponentFactory,
qsImplProvider,
shadeInteractor,
+ displayStateInteractor,
dumpManager,
testDispatcher,
testScope.backgroundScope,
@@ -583,6 +587,25 @@
}
@Test
+ fun setIsNotificationPanelFullWidth() =
+ testScope.runTest {
+ val qsImpl by collectLastValue(underTest.qsImpl)
+
+ underTest.inflate(context)
+ runCurrent()
+
+ kosmos.displayStateRepository.setIsLargeScreen(true)
+ runCurrent()
+
+ verify(qsImpl!!).setIsNotificationPanelFullWidth(false)
+
+ underTest.inflate(context)
+ runCurrent()
+
+ verify(qsImpl!!).setIsNotificationPanelFullWidth(false)
+ }
+
+ @Test
fun setBrightnessMirrorController() =
testScope.runTest {
val qsImpl by collectLastValue(underTest.qsImpl)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
index 4a7b887..40fb769 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
@@ -161,6 +161,7 @@
mShadeWindowLogger,
() -> mSelectedUserInteractor,
mUserTracker,
+ mKosmos.getNotificationShadeWindowModel(),
mKosmos::getCommunalInteractor) {
@Override
protected boolean isDebuggable() {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImplTest.kt
index aef9163..b917014 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImplTest.kt
@@ -124,4 +124,36 @@
underTest.setIsLaunchingActivity(true)
Truth.assertThat(underTest.isLaunchingActivity.value).isEqualTo(true)
}
+
+ @Test
+ fun isAnyFlingAnimationRunning() =
+ testScope.runTest() {
+ val actual by collectLastValue(underTest.isAnyFlingAnimationRunning)
+
+ // WHEN transitioning from QS to Gone with user input ongoing
+ val userInputOngoing = MutableStateFlow(true)
+ val transitionState =
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Transition(
+ fromScene = Scenes.QuickSettings,
+ toScene = Scenes.Gone,
+ currentScene = flowOf(Scenes.QuickSettings),
+ progress = MutableStateFlow(.1f),
+ isInitiatedByUserInput = true,
+ isUserInputOngoing = userInputOngoing,
+ )
+ )
+ sceneInteractor.setTransitionState(transitionState)
+ runCurrent()
+
+ // THEN qs is not flinging
+ Truth.assertThat(actual).isFalse()
+
+ // WHEN user input ends
+ userInputOngoing.value = false
+ runCurrent()
+
+ // THEN qs is flinging
+ Truth.assertThat(actual).isTrue()
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt
index cecc70c..d37e0fb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt
@@ -27,6 +27,7 @@
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.display.data.repository.displayStateRepository
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.flags.parameterizeSceneContainerFlag
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
@@ -41,6 +42,8 @@
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.shade.shared.flag.DualShade
import com.android.systemui.shade.shared.model.ShadeMode
+import com.android.systemui.statusbar.notification.stack.notificationStackScrollLayoutController
+import com.android.systemui.statusbar.phone.scrimController
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
@@ -54,6 +57,7 @@
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.kotlin.verify
import platform.test.runner.parameterized.ParameterizedAndroidJunit4
import platform.test.runner.parameterized.Parameters
@@ -167,6 +171,18 @@
}
}
+ @Test
+ @EnableSceneContainer
+ fun hydrateFullWidth() =
+ testScope.runTest {
+ underTest.start()
+
+ kosmos.displayStateRepository.setIsLargeScreen(true)
+ runCurrent()
+ verify(kosmos.notificationStackScrollLayoutController).setIsFullWidth(false)
+ assertThat(kosmos.scrimController.clipQsScrim).isFalse()
+ }
+
private fun TestScope.changeScene(
toScene: SceneKey,
transitionState: MutableStateFlow<ObservableTransitionState>,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModelTest.kt
new file mode 100644
index 0000000..add33da
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModelTest.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade.ui.viewmodel
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class NotificationShadeWindowModelTest : SysuiTestCase() {
+
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+ private val keyguardTransitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository }
+ private val underTest: NotificationShadeWindowModel by lazy {
+ kosmos.notificationShadeWindowModel
+ }
+
+ @Test
+ fun transitionToOccluded() =
+ testScope.runTest {
+ val isKeyguardOccluded by collectLastValue(underTest.isKeyguardOccluded)
+ assertThat(isKeyguardOccluded).isFalse()
+
+ keyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.OCCLUDED,
+ testScope,
+ )
+ assertThat(isKeyguardOccluded).isTrue()
+
+ keyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.OCCLUDED,
+ to = KeyguardState.GONE,
+ testScope,
+ )
+ assertThat(isKeyguardOccluded).isFalse()
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
index 343b6bd..3b2c981 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
@@ -25,7 +25,6 @@
import com.android.compose.animation.scene.Swipe
import com.android.compose.animation.scene.SwipeDirection
import com.android.systemui.SysuiTestCase
-import com.android.systemui.activatable.activateIn
import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
@@ -37,6 +36,7 @@
import com.android.systemui.keyguard.domain.interactor.keyguardEnabledInteractor
import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import com.android.systemui.kosmos.testScope
+import com.android.systemui.lifecycle.activateIn
import com.android.systemui.media.controls.data.repository.mediaFilterRepository
import com.android.systemui.media.controls.shared.model.MediaData
import com.android.systemui.qs.ui.adapter.fakeQSSceneAdapter
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractorTest.kt
index bec8cfe..9f40f60 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractorTest.kt
@@ -24,8 +24,11 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testScope
import com.android.systemui.statusbar.notification.collection.render.NotifStats
+import com.android.systemui.statusbar.notification.data.model.activeNotificationModel
+import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
import com.android.systemui.statusbar.notification.data.repository.setActiveNotifs
+import com.android.systemui.statusbar.notification.shared.CallType
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -56,6 +59,117 @@
}
@Test
+ fun ongoingCallNotification_noCallNotifs_null() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.ongoingCallNotification)
+
+ val normalNotifs =
+ listOf(
+ activeNotificationModel(
+ key = "notif1",
+ callType = CallType.None,
+ ),
+ activeNotificationModel(
+ key = "notif2",
+ callType = CallType.None,
+ )
+ )
+
+ activeNotificationListRepository.activeNotifications.value =
+ ActiveNotificationsStore.Builder()
+ .apply { normalNotifs.forEach(::addIndividualNotif) }
+ .build()
+
+ assertThat(latest).isNull()
+ }
+
+ @Test
+ fun ongoingCallNotification_incomingCallNotif_null() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.ongoingCallNotification)
+
+ activeNotificationListRepository.activeNotifications.value =
+ ActiveNotificationsStore.Builder()
+ .apply {
+ addIndividualNotif(
+ activeNotificationModel(
+ key = "incomingNotif",
+ callType = CallType.Incoming,
+ )
+ )
+ }
+ .build()
+
+ assertThat(latest).isNull()
+ }
+
+ @Test
+ fun ongoingCallNotification_screeningCallNotif_null() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.ongoingCallNotification)
+
+ activeNotificationListRepository.activeNotifications.value =
+ ActiveNotificationsStore.Builder()
+ .apply {
+ addIndividualNotif(
+ activeNotificationModel(
+ key = "screeningNotif",
+ callType = CallType.Screening,
+ )
+ )
+ }
+ .build()
+
+ assertThat(latest).isNull()
+ }
+
+ @Test
+ fun ongoingCallNotification_ongoingCallNotif_hasNotif() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.ongoingCallNotification)
+
+ val ongoingNotif =
+ activeNotificationModel(
+ key = "ongoingNotif",
+ callType = CallType.Ongoing,
+ )
+
+ activeNotificationListRepository.activeNotifications.value =
+ ActiveNotificationsStore.Builder()
+ .apply { addIndividualNotif(ongoingNotif) }
+ .build()
+
+ assertThat(latest).isEqualTo(ongoingNotif)
+ }
+
+ @Test
+ fun ongoingCallNotification_multipleCallNotifs_usesEarlierNotif() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.ongoingCallNotification)
+
+ val earlierOngoingNotif =
+ activeNotificationModel(
+ key = "earlierOngoingNotif",
+ callType = CallType.Ongoing,
+ whenTime = 45L,
+ )
+ val laterOngoingNotif =
+ activeNotificationModel(
+ key = "laterOngoingNotif",
+ callType = CallType.Ongoing,
+ whenTime = 55L,
+ )
+
+ activeNotificationListRepository.activeNotifications.value =
+ ActiveNotificationsStore.Builder()
+ .apply { addIndividualNotif(earlierOngoingNotif) }
+ .apply { addIndividualNotif(laterOngoingNotif) }
+ .build()
+
+ assertThat(latest).isEqualTo(earlierOngoingNotif)
+ }
+
+ @Test
fun areAnyNotificationsPresent_isTrue() =
testScope.runTest {
val areAnyNotificationsPresent by collectLastValue(underTest.areAnyNotificationsPresent)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt
index 88431f0..32f66c1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt
@@ -18,15 +18,21 @@
import android.app.NotificationManager.Policy
import android.provider.Settings
+import android.provider.Settings.Secure.ZEN_DURATION
+import android.provider.Settings.Secure.ZEN_DURATION_FOREVER
+import android.provider.Settings.Secure.ZEN_DURATION_PROMPT
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.settingslib.notification.data.repository.updateNotificationPolicy
+import com.android.settingslib.notification.modes.TestModeBuilder
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testScope
+import com.android.systemui.shared.settings.data.repository.secureSettingsRepository
import com.android.systemui.statusbar.policy.data.repository.fakeZenModeRepository
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
+import java.time.Duration
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
@@ -39,7 +45,8 @@
class ZenModeInteractorTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
- private val repository = kosmos.fakeZenModeRepository
+ private val zenModeRepository = kosmos.fakeZenModeRepository
+ private val settingsRepository = kosmos.secureSettingsRepository
private val underTest = kosmos.zenModeInteractor
@@ -48,7 +55,7 @@
testScope.runTest {
val enabled by collectLastValue(underTest.isZenModeEnabled)
- repository.updateZenMode(Settings.Global.ZEN_MODE_OFF)
+ zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_OFF)
runCurrent()
assertThat(enabled).isFalse()
@@ -59,7 +66,7 @@
testScope.runTest {
val enabled by collectLastValue(underTest.isZenModeEnabled)
- repository.updateZenMode(Settings.Global.ZEN_MODE_ALARMS)
+ zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_ALARMS)
runCurrent()
assertThat(enabled).isTrue()
@@ -70,7 +77,7 @@
testScope.runTest {
val enabled by collectLastValue(underTest.isZenModeEnabled)
- repository.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
+ zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
runCurrent()
assertThat(enabled).isTrue()
@@ -81,7 +88,7 @@
testScope.runTest {
val enabled by collectLastValue(underTest.isZenModeEnabled)
- repository.updateZenMode(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS)
+ zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS)
runCurrent()
assertThat(enabled).isTrue()
@@ -92,7 +99,8 @@
testScope.runTest {
val enabled by collectLastValue(underTest.isZenModeEnabled)
- repository.updateZenMode(4) // this should fail if we ever add another zen mode type
+ // this should fail if we ever add another zen mode type
+ zenModeRepository.updateZenMode(4)
runCurrent()
assertThat(enabled).isFalse()
@@ -103,8 +111,8 @@
testScope.runTest {
val hidden by collectLastValue(underTest.areNotificationsHiddenInShade)
- repository.updateNotificationPolicy(null)
- repository.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
+ zenModeRepository.updateNotificationPolicy(null)
+ zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
runCurrent()
assertThat(hidden).isFalse()
@@ -115,10 +123,10 @@
testScope.runTest {
val hidden by collectLastValue(underTest.areNotificationsHiddenInShade)
- repository.updateNotificationPolicy(
+ zenModeRepository.updateNotificationPolicy(
suppressedVisualEffects = Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST
)
- repository.updateZenMode(Settings.Global.ZEN_MODE_OFF)
+ zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_OFF)
runCurrent()
assertThat(hidden).isFalse()
@@ -129,10 +137,10 @@
testScope.runTest {
val hidden by collectLastValue(underTest.areNotificationsHiddenInShade)
- repository.updateNotificationPolicy(
+ zenModeRepository.updateNotificationPolicy(
suppressedVisualEffects = Policy.SUPPRESSED_EFFECT_STATUS_BAR
)
- repository.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
+ zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
runCurrent()
assertThat(hidden).isFalse()
@@ -143,12 +151,70 @@
testScope.runTest {
val hidden by collectLastValue(underTest.areNotificationsHiddenInShade)
- repository.updateNotificationPolicy(
+ zenModeRepository.updateNotificationPolicy(
suppressedVisualEffects = Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST
)
- repository.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
+ zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
runCurrent()
assertThat(hidden).isTrue()
}
+
+ @Test
+ fun shouldAskForZenDuration_falseForNonManualDnd() =
+ testScope.runTest {
+ settingsRepository.setInt(ZEN_DURATION, ZEN_DURATION_PROMPT)
+ runCurrent()
+
+ assertThat(underTest.shouldAskForZenDuration(TestModeBuilder.EXAMPLE)).isFalse()
+ }
+
+ @Test
+ fun shouldAskForZenDuration_changesWithSetting() =
+ testScope.runTest {
+ val manualDnd = TestModeBuilder.MANUAL_DND
+
+ settingsRepository.setInt(ZEN_DURATION, ZEN_DURATION_FOREVER)
+ runCurrent()
+
+ assertThat(underTest.shouldAskForZenDuration(manualDnd)).isFalse()
+
+ settingsRepository.setInt(ZEN_DURATION, ZEN_DURATION_PROMPT)
+ runCurrent()
+
+ assertThat(underTest.shouldAskForZenDuration(manualDnd)).isTrue()
+ }
+
+ @Test
+ fun activateMode_nonManualDnd() =
+ testScope.runTest {
+ val mode = TestModeBuilder().setActive(false).build()
+ zenModeRepository.addModes(listOf(mode))
+ settingsRepository.setInt(ZEN_DURATION, 60)
+ runCurrent()
+
+ underTest.activateMode(mode)
+ assertThat(zenModeRepository.getMode(mode.id)?.isActive).isTrue()
+ assertThat(zenModeRepository.getModeActiveDuration(mode.id)).isNull()
+ }
+
+ @Test
+ fun activateMode_usesCorrectDuration() =
+ testScope.runTest {
+ val manualDnd = TestModeBuilder.MANUAL_DND
+ zenModeRepository.addModes(listOf(manualDnd))
+ settingsRepository.setInt(ZEN_DURATION, ZEN_DURATION_FOREVER)
+ runCurrent()
+
+ underTest.activateMode(manualDnd)
+ assertThat(zenModeRepository.getModeActiveDuration(manualDnd.id)).isNull()
+
+ zenModeRepository.deactivateMode(manualDnd.id)
+ settingsRepository.setInt(ZEN_DURATION, 60)
+ runCurrent()
+
+ underTest.activateMode(manualDnd)
+ assertThat(zenModeRepository.getModeActiveDuration(manualDnd.id))
+ .isEqualTo(Duration.ofMinutes(60))
+ }
}
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 bf58eee..d3218ad 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
@@ -14,6 +14,7 @@
package com.android.systemui.plugins.qs;
+import android.graphics.Rect;
import android.view.View;
import androidx.annotation.FloatRange;
@@ -35,7 +36,7 @@
String ACTION = "com.android.systemui.action.PLUGIN_QS";
- int VERSION = 15;
+ int VERSION = 16;
String TAG = "QS";
@@ -89,8 +90,45 @@
*/
int getHeightDiff();
+ /**
+ * Returns the header view that contains QQS. This might return null (or throw) if there's no
+ * actual header view.
+ */
View getHeader();
+ /**
+ * Returns the top of the header view that contains QQS wrt to the container view
+ */
+ int getHeaderTop();
+
+ /**
+ * Returns the bottom of the header view that contains QQS wrt to the container view
+ */
+ int getHeaderBottom();
+
+ /**
+ * Returns the left bound of the header view that contains QQS wrt to the container view
+ */
+ int getHeaderLeft();
+
+ /**
+ * Fills outBounds with the bounds of the header view (container of QQS) on the screen
+ */
+ void getHeaderBoundsOnScreen(Rect outBounds);
+
+ /**
+ * Returns the height of the header view that contains QQS. It defaults to bottom - top.
+ */
+ default int getHeaderHeight() {
+ return getHeaderBottom() - getHeaderTop();
+ }
+
+ /**
+ * Returns whether the header view that contains QQS is shown on screen (similar semantics to
+ * View.isShown).
+ */
+ boolean isHeaderShown();
+
default void setHasNotifications(boolean hasNotifications) {
}
diff --git a/packages/SystemUI/res/drawable/brightness_bar.xml b/packages/SystemUI/res/drawable/brightness_bar.xml
new file mode 100644
index 0000000..2afe164
--- /dev/null
+++ b/packages/SystemUI/res/drawable/brightness_bar.xml
@@ -0,0 +1,36 @@
+<!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:width="200dp"
+ android:height="32dp"
+ android:viewportWidth="304"
+ android:viewportHeight="48">
+<path
+ android:pathData="M2,22L302,22A2,2 0,0 1,304 24L304,24A2,2 0,0 1,302 26L2,26A2,2 0,0 1,0 24L0,24A2,2 0,0 1,2 22z"
+ android:fillColor="@color/brightness_slider_track"/>
+<path
+ android:pathData="M24,0L205.71,0A24,24 0,0 1,229.71 24L229.71,24A24,24 0,0 1,205.71 48L24,48A24,24 0,0 1,0 24L0,24A24,24 0,0 1,24 0z"
+ android:fillColor="?attr/shadeActive"/>
+<path
+ android:pathData="M0,24C0,10.75 10.75,0 24,0H63.85V48H24C10.75,48 0,37.25 0,24Z"
+ android:fillColor="?androidprv:attr/colorAccentPrimaryVariant"/>
+<path
+ android:pathData="M208.98,21.26V17.37H205.09L202.34,14.62L199.6,17.37H195.71V21.26L192.96,24L195.71,26.75V30.63H199.6L202.34,33.38L205.09,30.63H208.98V26.75L211.72,24L208.98,21.26ZM207.32,26.06V28.98H204.4L202.34,31.03L200.29,28.98H197.37V26.06L195.31,24L197.37,21.94V19.02H200.29L202.34,16.97L204.4,19.02H207.32V21.94L209.37,24L207.32,26.06ZM206.49,24C206.49,26.29 204.63,28.15 202.34,28.15V19.85C204.63,19.85 206.49,21.71 206.49,24Z"
+ android:fillColor="?attr/onShadeActive"
+ android:fillType="evenOdd"/>
+</vector>
+
diff --git a/packages/SystemUI/res/drawable/ic_redacted_notification_single_line_icon.xml b/packages/SystemUI/res/drawable/ic_redacted_notification_single_line_icon.xml
new file mode 100644
index 0000000..8146c16
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_redacted_notification_single_line_icon.xml
@@ -0,0 +1,27 @@
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32dp"
+ android:height="32dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="?android:attr/colorAccent"
+ android:pathData="M12,15m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
+ <path
+ android:fillColor="?android:attr/colorAccent"
+ android:pathData="M18,8h-1.5V5.5C16.5,3.01 14.49,1 12,1S7.5,3.01 7.5,5.5V8H6c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V10C20,8.9 19.1,8 18,8zM9.5,5.5C9.5,4.12 10.62,3 12,3c1.38,0 2.5,1.12 2.5,2.5V8h-5V5.5zM18,20H6V10h1.5h9H18V20z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/accessibility_deprecate_extra_dim_dialog.xml b/packages/SystemUI/res/layout/accessibility_deprecate_extra_dim_dialog.xml
new file mode 100644
index 0000000..e839f4c
--- /dev/null
+++ b/packages/SystemUI/res/layout/accessibility_deprecate_extra_dim_dialog.xml
@@ -0,0 +1,41 @@
+<!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/illustration_frame"
+ android:orientation="vertical"
+ android:paddingHorizontal="16dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center">
+
+ <ImageView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:adjustViewBounds="true"
+ android:layout_marginVertical="24dp"
+ android:scaleType="fitCenter"
+ android:importantForAccessibility="no"
+ android:theme="@style/Theme.SystemUI.QuickSettings"
+ android:src="@drawable/brightness_bar"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:textSize="16sp"
+ android:text="@string/accessibility_deprecate_extra_dim_dialog_description"
+ android:textAppearance="@style/TextAppearance.Dialog.Body"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/biometric_prompt_one_pane_layout.xml b/packages/SystemUI/res/layout/biometric_prompt_one_pane_layout.xml
index 4670f34..3b3ed39 100644
--- a/packages/SystemUI/res/layout/biometric_prompt_one_pane_layout.xml
+++ b/packages/SystemUI/res/layout/biometric_prompt_one_pane_layout.xml
@@ -10,7 +10,7 @@
android:id="@+id/background"
android:layout_width="0dp"
android:layout_height="0dp"
- android:contentDescription="@string/biometric_dialog_empty_space_description"
+ android:contentDescription="@string/cancel"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
diff --git a/packages/SystemUI/res/layout/biometric_prompt_two_pane_layout.xml b/packages/SystemUI/res/layout/biometric_prompt_two_pane_layout.xml
index c599f9e..2a00495 100644
--- a/packages/SystemUI/res/layout/biometric_prompt_two_pane_layout.xml
+++ b/packages/SystemUI/res/layout/biometric_prompt_two_pane_layout.xml
@@ -11,7 +11,7 @@
android:id="@+id/background"
android:layout_width="0dp"
android:layout_height="0dp"
- android:contentDescription="@string/biometric_dialog_empty_space_description"
+ android:contentDescription="@string/cancel"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@@ -87,20 +87,21 @@
android:id="@+id/logo_description"
style="@style/TextAppearance.AuthCredential.LogoDescription"
android:layout_width="0dp"
- android:layout_height="wrap_content"
+ android:layout_height="@dimen/biometric_prompt_logo_size"
+ android:gravity="start|center_vertical"
android:textAlignment="viewStart"
- android:paddingStart="16dp"
- app:layout_constraintBottom_toBottomOf="@+id/logo"
+ android:layout_marginStart="16dp"
+ app:layout_goneMarginStart="0dp"
+ app:layout_constraintBottom_toTopOf="@+id/title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/logo"
- app:layout_constraintTop_toTopOf="@+id/logo" />
+ app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/title"
style="@style/TextAppearance.AuthCredential.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="12dp"
android:gravity="@integer/biometric_dialog_text_gravity"
android:paddingHorizontal="0dp"
android:textAlignment="viewStart"
@@ -108,7 +109,7 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/logo"
+ app:layout_constraintTop_toBottomOf="@+id/logoBarrier"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintVertical_chainStyle="packed" />
@@ -159,6 +160,15 @@
app:layout_constraintVertical_bias="0.0" />
<androidx.constraintlayout.widget.Barrier
+ android:id="@+id/logoBarrier"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:barrierMargin="12dp"
+ app:barrierAllowsGoneWidgets="false"
+ app:barrierDirection="bottom"
+ app:constraint_referenced_ids="logo_description, logo" />
+
+ <androidx.constraintlayout.widget.Barrier
android:id="@+id/contentBarrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/layout/hearing_tool_item.xml b/packages/SystemUI/res/layout/hearing_tool_item.xml
index 84462d0..ff2fbe07 100644
--- a/packages/SystemUI/res/layout/hearing_tool_item.xml
+++ b/packages/SystemUI/res/layout/hearing_tool_item.xml
@@ -20,7 +20,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:gravity="center"
+ android:gravity="top|center_horizontal"
android:focusable="true"
android:clickable="true"
android:layout_weight="1">
@@ -46,8 +46,8 @@
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/hearing_devices_layout_margin"
android:ellipsize="end"
- android:maxLines="1"
android:textSize="12sp"
+ android:maxLines="3"
android:textAppearance="@style/TextAppearance.Dialog.Body.Message"
android:focusable="false" />
</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/record_issue_dialog.xml b/packages/SystemUI/res/layout/record_issue_dialog.xml
index 30d7b0a..e30ae6e 100644
--- a/packages/SystemUI/res/layout/record_issue_dialog.xml
+++ b/packages/SystemUI/res/layout/record_issue_dialog.xml
@@ -35,7 +35,7 @@
android:layout_height="wrap_content"
android:text="@string/qs_record_issue_dropdown_prompt"
android:lines="1"
- android:drawableRight="@drawable/arrow_pointing_down"
+ android:drawableEnd="@drawable/arrow_pointing_down"
android:layout_marginTop="@dimen/qqs_layout_margin_top"
android:focusable="false"
android:clickable="true" />
diff --git a/packages/SystemUI/res/raw/biometricprompt_fingerprint_to_error_landscape.json b/packages/SystemUI/res/raw/biometricprompt_fingerprint_to_error_landscape.json
deleted file mode 100644
index 3d33b2a..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_fingerprint_to_error_landscape.json
+++ /dev/null
@@ -1 +0,0 @@
-{"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_folded_base_bottomright.json b/packages/SystemUI/res/raw/biometricprompt_folded_base_bottomright.json
deleted file mode 100644
index 2797996..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_folded_base_bottomright.json
+++ /dev/null
@@ -1 +0,0 @@
-{"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}]}
diff --git a/packages/SystemUI/res/raw/biometricprompt_folded_base_default.json b/packages/SystemUI/res/raw/biometricprompt_folded_base_default.json
deleted file mode 100644
index bf65b34..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_folded_base_default.json
+++ /dev/null
@@ -1 +0,0 @@
-{"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}]}
diff --git a/packages/SystemUI/res/raw/biometricprompt_folded_base_topleft.json b/packages/SystemUI/res/raw/biometricprompt_folded_base_topleft.json
deleted file mode 100644
index 7351d7c..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_folded_base_topleft.json
+++ /dev/null
@@ -1 +0,0 @@
-{"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":".grey600","cl":"grey600","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":".grey900","cl":"grey900","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":".grey900","cl":"grey900","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":".grey900","cl":"grey900","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":".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":[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}]}
diff --git a/packages/SystemUI/res/raw/biometricprompt_landscape_base.json b/packages/SystemUI/res/raw/biometricprompt_landscape_base.json
deleted file mode 100644
index 3781eee..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_landscape_base.json
+++ /dev/null
@@ -1 +0,0 @@
-{"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
deleted file mode 100644
index 4950666..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_portrait_base_bottomright.json
+++ /dev/null
@@ -1 +0,0 @@
-{"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
deleted file mode 100644
index 09ed225..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_portrait_base_topleft.json
+++ /dev/null
@@ -1 +0,0 @@
-{"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":".grey600","cl":"grey600","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":".grey900","cl":"grey900","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":".grey900","cl":"grey900","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":".grey900","cl":"grey900","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":".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":[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_rear_landscape_base.json b/packages/SystemUI/res/raw/biometricprompt_rear_landscape_base.json
deleted file mode 100644
index 49c1c40..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_rear_landscape_base.json
+++ /dev/null
@@ -1 +0,0 @@
-{"v":"5.8.1","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"BiometricPrompt_Rear_Landscape_Base_Foldable","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 18","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[169.478,169.749,0],"ix":2,"l":2},"a":{"a":0,"k":[-48.123,-30.19,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},{"ddd":0,"ind":2,"ty":4,"nm":".grey400","cl":"grey400","parent":13,"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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,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":[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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"black circle matte","parent":13,"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,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":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey904","cl":"grey904","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-62.577,35.536,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],[-2.552,0.087],[0,0]],"o":[[0,0],[0,-3.287],[0,0],[0,0]],"v":[[-2.301,8.869],[-2.301,-3.772],[2.301,-9.806],[2.301,9.806]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"black circle matte 2","parent":13,"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,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":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".blue401","cl":"blue401","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-62.577,-27.655,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,3.286],[0,0],[-2.552,0.086],[0,0]],"o":[[0,0],[0,-3.286],[0,0],[-2.552,-0.086]],"v":[[-2.301,16.282],[-2.301,-16.281],[2.301,-22.313],[2.301,22.313]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"black circle matte 3","parent":13,"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,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":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Finger 2","parent":1,"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":-129,"s":[-67]},{"t":-29,"s":[0]}],"ix":10},"p":{"a":0,"k":[-75.352,41.307,0],"ix":2,"l":2},"a":{"a":0,"k":[94.648,211.307,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[6.72,-5.642],[0,0],[-9.394,-0.562],[-0.298,-0.038]],"o":[[-5.153,4.329],[3.882,-16.05],[0.31,0.019],[-0.044,0.75]],"v":[[0.863,12.222],[-8.931,14.755],[8.005,-15.108],[8.931,-15.021]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[81.486,130.081],"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":"Layer 9","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.459,6.045],[-5.153,4.329],[-0.044,0.75],[3.116,-24.664],[5.23,-22.052],[8.666,11.92],[-2.9,9.135]],"o":[[0,0],[6.72,-5.642],[12.723,1.335],[-2.369,18.762],[-13.993,-5.333],[2.255,-5.502],[1.843,-5.815]],"v":[[-9.99,-18.348],[-0.196,-20.881],[7.872,-48.124],[21.578,-9.331],[12.104,48.124],[-22.574,21.555],[-14.791,-0.206]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[82.545,163.184],"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":"Layer 8","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"black circle matte 4","parent":13,"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,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":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".grey903","cl":"grey903","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-18.345,-92.442,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":[[24.07,0],[0,0],[-8.27,0],[0,0]],"o":[[0,0],[0,8.269],[0,0],[-14.024,-17.379]],"v":[[-29.778,-14.252],[-29.778,-0.721],[-14.805,14.252],[29.778,14.252]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549027205,0.388235300779,0.407843142748,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"black circle matte 5","parent":13,"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,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":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".grey902","cl":"grey902","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-15.947,-30.19,0],"ix":2,"l":2},"a":{"a":0,"k":[154.053,139.81,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.3,0.367],[0,0],[-2.364,0.157],[0,0]],"o":[[0,0],[2.3,-0.367],[0,0],[-2.364,-0.157]],"v":[[-3.5,75.533],[-3.5,-75.533],[3.5,-76.312],[3.5,76.312]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[113.225,139.81],"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":"Layer 7","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,8.269],[0,0],[2.181,-0.187],[0,0],[-2.23,0],[0,42.252],[10.593,13.127],[0,0]],"o":[[0,0],[-2.23,0],[0,0],[2.181,0.187],[42.252,0],[0,-18.182],[0,0],[-8.27,0]],"v":[[-34.946,-62.973],[-34.946,-76.504],[-41.558,-76.201],[-41.558,76.201],[-34.946,76.504],[41.558,0],[24.61,-48],[-19.973,-48]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[156.824,139.81],"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":"Layer 5","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".black 2","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-48.123,-30.19,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,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":-129,"s":[0,0,100]},{"t":-79,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".grey700","cl":"grey700","parent":15,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-56.481,-59.936,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":[[3.767,0],[0,0],[0,-3.767],[0,0],[-3.767,0],[0,0],[0,3.767],[0,0]],"o":[[0,0],[-3.767,0],[0,0],[0,3.767],[0,0],[3.767,0],[0,0],[0,-3.767]],"v":[[46.055,-14.479],[-46.056,-14.479],[-52.876,-7.659],[-52.876,7.658],[-46.056,14.479],[46.055,14.479],[52.876,7.658],[52.876,-7.659]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549027205,0.388235300779,0.407843142748,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".grey901","cl":"grey901","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16.485,2.727,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[50,50,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[4.184,0],[0,0],[0,0],[0,0],[0,-4.375]],"o":[[0,4.184],[0,0],[0,0],[0,0],[4.375,0],[0,0]],"v":[[114.116,92.129],[106.54,99.705],[7.788,99.705],[7.788,-99.704],[106.161,-99.704],[114.116,-91.749]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[5.707,0],[0,0],[1.894,-1.05],[0.886,0.346],[0,0],[2.166,0],[0,0],[0,-5.707],[0,0],[0,-1.46],[0,0],[-1.133,-0.038],[0,0],[0,-1.459],[0,0],[-1.133,-0.038],[0,0],[-5.708,0],[0,0],[-1.894,1.05],[-0.846,-0.289],[0,0],[-2.166,0],[0,0],[0,5.706],[0,0]],"o":[[0,0],[-2.166,0],[-0.883,0.354],[0,0],[-1.895,-1.05],[0,0],[-5.708,0],[0,0],[-1.133,0.038],[0,0],[0,1.46],[0,0],[-1.133,0.038],[0,0],[0,1.46],[0,0],[0,5.707],[0,0],[2.165,0],[0.833,-0.334],[0,0],[1.894,1.05],[0,0],[5.707,0],[0,0],[0,-5.707]],"v":[[106.16,-102.082],[8.455,-102.082],[2.265,-100.48],[-0.488,-100.468],[-0.519,-100.48],[-6.71,-102.082],[-104.116,-102.082],[-114.45,-91.748],[-114.45,-36.119],[-116.494,-33.44],[-116.494,-18.979],[-114.45,-16.3],[-114.45,-0.877],[-116.494,1.802],[-116.494,28.704],[-114.45,31.383],[-114.45,91.749],[-104.116,102.083],[-6.495,102.083],[-0.305,100.481],[2.294,100.425],[2.395,100.481],[9.872,102.083],[106.161,102.083],[116.494,91.75],[116.494,-91.748]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.529411792755,0.54509806633,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":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"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_rear_portrait_base.json b/packages/SystemUI/res/raw/biometricprompt_rear_portrait_base.json
deleted file mode 100644
index 9ea0d35..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_rear_portrait_base.json
+++ /dev/null
@@ -1 +0,0 @@
-{"v":"5.8.1","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"BiometricPrompt_Rear_Portrait_Base_Foldable","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 18","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[169.478,169.749,0],"ix":2,"l":2},"a":{"a":0,"k":[-48.123,-30.19,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},{"ddd":0,"ind":2,"ty":4,"nm":".grey400","cl":"grey400","parent":14,"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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,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":[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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"black circle matte","parent":14,"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,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":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey904","cl":"grey904","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-62.577,35.536,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],[-2.552,0.087],[0,0]],"o":[[0,0],[0,-3.287],[0,0],[0,0]],"v":[[-2.301,8.869],[-2.301,-3.772],[2.301,-9.806],[2.301,9.806]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"black circle matte 2","parent":14,"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,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":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".blue401","cl":"blue401","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-62.577,-27.655,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,3.286],[0,0],[-2.552,0.086],[0,0]],"o":[[0,0],[0,-3.286],[0,0],[-2.552,-0.086]],"v":[[-2.301,16.282],[-2.301,-16.281],[2.301,-22.313],[2.301,22.313]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"black circle matte 3","parent":14,"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,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":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Finger 3","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-2,"ix":10},"p":{"a":0,"k":[260.134,83.782,0],"ix":2,"l":2},"a":{"a":0,"k":[302.634,38.782,0],"ix":1,"l":2},"s":{"a":0,"k":[178,178,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.262,5.076],[0,0],[-0.424,-7.095],[-0.028,-0.225]],"o":[[3.269,-3.892],[-12.123,2.932],[0.015,0.234],[0.567,-0.034]],"v":[[9.232,0.652],[11.145,-6.746],[-11.412,6.046],[-11.346,6.746]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[241.281,55.033],"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":"Layer 5","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[4.565,-1.102],[3.269,-3.892],[0.566,-0.033],[-18.63,2.353],[-16.656,3.951],[9.004,6.546],[6.9,-2.19]],"o":[[0,0],[-4.262,5.076],[1.008,9.61],[14.171,-1.79],[-4.028,-10.569],[-4.156,1.703],[-4.392,1.392]],"v":[[-13.858,-7.546],[-15.771,-0.148],[-36.349,5.946],[-7.047,16.299],[36.349,9.142],[16.281,-17.051],[-0.156,-11.172]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[266.285,55.833],"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":"Layer 4","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"black circle matte 4","parent":14,"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,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":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":".grey903","cl":"grey903","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-18.345,-92.442,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":[[24.07,0],[0,0],[-8.27,0],[0,0]],"o":[[0,0],[0,8.269],[0,0],[-14.024,-17.379]],"v":[[-29.778,-14.252],[-29.778,-0.721],[-14.805,14.252],[29.778,14.252]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549027205,0.388235300779,0.407843142748,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"black circle matte 5","parent":14,"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,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":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".grey902","cl":"grey902","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-15.947,-30.19,0],"ix":2,"l":2},"a":{"a":0,"k":[154.053,139.81,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.3,0.367],[0,0],[-2.364,0.157],[0,0]],"o":[[0,0],[2.3,-0.367],[0,0],[-2.364,-0.157]],"v":[[-3.5,75.533],[-3.5,-75.533],[3.5,-76.312],[3.5,76.312]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[113.225,139.81],"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":"Layer 7","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,8.269],[0,0],[2.181,-0.187],[0,0],[-2.23,0],[0,42.252],[10.593,13.127],[0,0]],"o":[[0,0],[-2.23,0],[0,0],[2.181,0.187],[42.252,0],[0,-18.182],[0,0],[-8.27,0]],"v":[[-34.946,-62.973],[-34.946,-76.504],[-41.558,-76.201],[-41.558,76.201],[-34.946,76.504],[41.558,0],[24.61,-48],[-19.973,-48]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[156.824,139.81],"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":"Layer 5","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".black 2","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-48.123,-30.19,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,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":-129,"s":[0,0,100]},{"t":-79,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".grey700","cl":"grey700","parent":16,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-56.481,-59.936,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":[[3.767,0],[0,0],[0,-3.767],[0,0],[-3.767,0],[0,0],[0,3.767],[0,0]],"o":[[0,0],[-3.767,0],[0,0],[0,3.767],[0,0],[3.767,0],[0,0],[0,-3.767]],"v":[[46.055,-14.479],[-46.056,-14.479],[-52.876,-7.659],[-52.876,7.658],[-46.056,14.479],[46.055,14.479],[52.876,7.658],[52.876,-7.659]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549027205,0.388235300779,0.407843142748,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".grey901","cl":"grey901","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16.485,2.727,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[50,50,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[4.184,0],[0,0],[0,0],[0,0],[0,-4.375]],"o":[[0,4.184],[0,0],[0,0],[0,0],[4.375,0],[0,0]],"v":[[114.116,92.129],[106.54,99.705],[7.788,99.705],[7.788,-99.704],[106.161,-99.704],[114.116,-91.749]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[5.707,0],[0,0],[1.894,-1.05],[0.886,0.346],[0,0],[2.166,0],[0,0],[0,-5.707],[0,0],[0,-1.46],[0,0],[-1.133,-0.038],[0,0],[0,-1.459],[0,0],[-1.133,-0.038],[0,0],[-5.708,0],[0,0],[-1.894,1.05],[-0.846,-0.289],[0,0],[-2.166,0],[0,0],[0,5.706],[0,0]],"o":[[0,0],[-2.166,0],[-0.883,0.354],[0,0],[-1.895,-1.05],[0,0],[-5.708,0],[0,0],[-1.133,0.038],[0,0],[0,1.46],[0,0],[-1.133,0.038],[0,0],[0,1.46],[0,0],[0,5.707],[0,0],[2.165,0],[0.833,-0.334],[0,0],[1.894,1.05],[0,0],[5.707,0],[0,0],[0,-5.707]],"v":[[106.16,-102.082],[8.455,-102.082],[2.265,-100.48],[-0.488,-100.468],[-0.519,-100.48],[-6.71,-102.082],[-104.116,-102.082],[-114.45,-91.748],[-114.45,-36.119],[-116.494,-33.44],[-116.494,-18.979],[-114.45,-16.3],[-114.45,-0.877],[-116.494,1.802],[-116.494,28.704],[-114.45,31.383],[-114.45,91.749],[-104.116,102.083],[-6.495,102.083],[-0.305,100.481],[2.294,100.425],[2.395,100.481],[9.872,102.083],[106.161,102.083],[116.494,91.75],[116.494,-91.748]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.529411792755,0.54509806633,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":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"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_rear_portrait_reverse_base.json b/packages/SystemUI/res/raw/biometricprompt_rear_portrait_reverse_base.json
deleted file mode 100644
index f2b2593..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_rear_portrait_reverse_base.json
+++ /dev/null
@@ -1 +0,0 @@
-{"v":"5.8.1","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"BiometricPrompt_Rear_Portrait_Reverse_Base_Foldable","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 18","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":270,"ix":10},"p":{"a":0,"k":[169.478,169.749,0],"ix":2,"l":2},"a":{"a":0,"k":[-48.123,-30.19,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},{"ddd":0,"ind":2,"ty":4,"nm":".grey400","cl":"grey400","parent":13,"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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,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":[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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"black circle matte","parent":13,"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,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":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey904","cl":"grey904","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-62.577,35.536,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],[-2.552,0.087],[0,0]],"o":[[0,0],[0,-3.287],[0,0],[0,0]],"v":[[-2.301,8.869],[-2.301,-3.772],[2.301,-9.806],[2.301,9.806]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"black circle matte 2","parent":13,"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,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":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".blue401","cl":"blue401","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-62.577,-27.655,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,3.286],[0,0],[-2.552,0.086],[0,0]],"o":[[0,0],[0,-3.286],[0,0],[-2.552,-0.086]],"v":[[-2.301,16.282],[-2.301,-16.281],[2.301,-22.313],[2.301,22.313]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"black circle matte 3","parent":13,"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,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":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-75.352,41.307,0],"ix":2,"l":2},"a":{"a":0,"k":[94.648,211.307,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[6.72,-5.642],[0,0],[-9.394,-0.562],[-0.298,-0.038]],"o":[[-5.153,4.329],[3.882,-16.05],[0.31,0.019],[-0.044,0.75]],"v":[[0.863,12.222],[-8.931,14.755],[8.005,-15.108],[8.931,-15.021]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[81.486,130.081],"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":"Layer 9","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.459,6.045],[-5.153,4.329],[-0.044,0.75],[3.116,-24.664],[5.23,-22.052],[8.666,11.92],[-2.9,9.135]],"o":[[0,0],[6.72,-5.642],[12.723,1.335],[-2.369,18.762],[-13.993,-5.333],[2.255,-5.502],[1.843,-5.815]],"v":[[-9.99,-18.348],[-0.196,-20.881],[7.872,-48.124],[21.578,-9.331],[12.104,48.124],[-22.574,21.555],[-14.791,-0.206]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[82.545,163.184],"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":"Layer 8","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"black circle matte 4","parent":13,"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,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":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".grey903","cl":"grey903","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-18.345,-92.442,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":[[24.07,0],[0,0],[-8.27,0],[0,0]],"o":[[0,0],[0,8.269],[0,0],[-14.024,-17.379]],"v":[[-29.778,-14.252],[-29.778,-0.721],[-14.805,14.252],[29.778,14.252]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549027205,0.388235300779,0.407843142748,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"black circle matte 5","parent":13,"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,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":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".grey902","cl":"grey902","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-15.947,-30.19,0],"ix":2,"l":2},"a":{"a":0,"k":[154.053,139.81,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.3,0.367],[0,0],[-2.364,0.157],[0,0]],"o":[[0,0],[2.3,-0.367],[0,0],[-2.364,-0.157]],"v":[[-3.5,75.533],[-3.5,-75.533],[3.5,-76.312],[3.5,76.312]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[113.225,139.81],"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":"Layer 7","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,8.269],[0,0],[2.181,-0.187],[0,0],[-2.23,0],[0,42.252],[10.593,13.127],[0,0]],"o":[[0,0],[-2.23,0],[0,0],[2.181,0.187],[42.252,0],[0,-18.182],[0,0],[-8.27,0]],"v":[[-34.946,-62.973],[-34.946,-76.504],[-41.558,-76.201],[-41.558,76.201],[-34.946,76.504],[41.558,0],[24.61,-48],[-19.973,-48]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[156.824,139.81],"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":"Layer 5","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".black 2","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-48.123,-30.19,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,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":-129,"s":[0,0,100]},{"t":-79,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".grey700","cl":"grey700","parent":15,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-56.481,-59.936,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":[[3.767,0],[0,0],[0,-3.767],[0,0],[-3.767,0],[0,0],[0,3.767],[0,0]],"o":[[0,0],[-3.767,0],[0,0],[0,3.767],[0,0],[3.767,0],[0,0],[0,-3.767]],"v":[[46.055,-14.479],[-46.056,-14.479],[-52.876,-7.659],[-52.876,7.658],[-46.056,14.479],[46.055,14.479],[52.876,7.658],[52.876,-7.659]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549027205,0.388235300779,0.407843142748,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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".grey901","cl":"grey901","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16.485,2.727,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[50,50,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[4.184,0],[0,0],[0,0],[0,0],[0,-4.375]],"o":[[0,4.184],[0,0],[0,0],[0,0],[4.375,0],[0,0]],"v":[[114.116,92.129],[106.54,99.705],[7.788,99.705],[7.788,-99.704],[106.161,-99.704],[114.116,-91.749]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[5.707,0],[0,0],[1.894,-1.05],[0.886,0.346],[0,0],[2.166,0],[0,0],[0,-5.707],[0,0],[0,-1.46],[0,0],[-1.133,-0.038],[0,0],[0,-1.459],[0,0],[-1.133,-0.038],[0,0],[-5.708,0],[0,0],[-1.894,1.05],[-0.846,-0.289],[0,0],[-2.166,0],[0,0],[0,5.706],[0,0]],"o":[[0,0],[-2.166,0],[-0.883,0.354],[0,0],[-1.895,-1.05],[0,0],[-5.708,0],[0,0],[-1.133,0.038],[0,0],[0,1.46],[0,0],[-1.133,0.038],[0,0],[0,1.46],[0,0],[0,5.707],[0,0],[2.165,0],[0.833,-0.334],[0,0],[1.894,1.05],[0,0],[5.707,0],[0,0],[0,-5.707]],"v":[[106.16,-102.082],[8.455,-102.082],[2.265,-100.48],[-0.488,-100.468],[-0.519,-100.48],[-6.71,-102.082],[-104.116,-102.082],[-114.45,-91.748],[-114.45,-36.119],[-116.494,-33.44],[-116.494,-18.979],[-114.45,-16.3],[-114.45,-0.877],[-116.494,1.802],[-116.494,28.704],[-114.45,31.383],[-114.45,91.749],[-104.116,102.083],[-6.495,102.083],[-0.305,100.481],[2.294,100.425],[2.395,100.481],[9.872,102.083],[106.161,102.083],[116.494,91.75],[116.494,-91.748]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.529411792755,0.54509806633,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":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"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_sfps_error_to_fingerprint.json b/packages/SystemUI/res/raw/biometricprompt_sfps_error_to_fingerprint.json
new file mode 100644
index 0000000..fa6fc07
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_error_to_fingerprint.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":240,"op":421,"w":150,"h":150,"nm":"BM_Prompt_Error-to-FP_0and180","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":170,"s":[43.5,43.5,100]},{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":240,"s":[43.5,43.5,100]},{"t":260,"s":[64,64,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red400","cl":"red400","parent":4,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.484,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.91,0.191,0],"ix":1,"l":2},"s":{"a":0,"k":[229.885,229.885,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[4,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,-7.079],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".red400","cl":"red400","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.889,9.487,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.889,7.487,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":[4,4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,7.491],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".red400","cl":"red400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.933333333333,0.403921568627,0.360784313725,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Matte 3","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Nail 2","parent":11,"tt":1,"tp":8,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Matte 2","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"tp":10,"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":320,"s":[43]},{"t":365,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":320,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":365,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Nail","parent":15,"tt":1,"tp":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":14,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":320,"s":[50]},{"t":390,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":290,"s":[0,0,100]},{"t":380,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":290,"op":391,"st":290,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":290,"s":[50]},{"t":360,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":260,"s":[0,0,100]},{"t":350,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":391,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":131,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":131,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_error_to_fingerprint_180.json b/packages/SystemUI/res/raw/biometricprompt_sfps_error_to_fingerprint_180.json
new file mode 100755
index 0000000..688ed7b
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_error_to_fingerprint_180.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":240,"op":421,"w":150,"h":150,"nm":"BM_Prompt_Error-to-FP_left","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[-64,64,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":170,"s":[-43.5,43.5,100]},{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":240,"s":[-43.5,43.5,100]},{"t":260,"s":[-64,64,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red400","cl":"red400","parent":4,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.484,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.91,0.191,0],"ix":1,"l":2},"s":{"a":0,"k":[229.885,229.885,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[4,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,-7.079],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".red400","cl":"red400","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.889,9.487,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.889,7.487,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":[4,4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,7.491],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".red400","cl":"red400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.933333333333,0.403921568627,0.360784313725,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Matte 3","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Nail 2","parent":11,"tt":1,"tp":8,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Matte 2","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"tp":10,"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":320,"s":[43]},{"t":365,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":320,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":365,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Nail","parent":15,"tt":1,"tp":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":14,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":320,"s":[50]},{"t":390,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":290,"s":[0,0,100]},{"t":380,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":290,"op":391,"st":290,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":290,"s":[50]},{"t":360,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":260,"s":[0,0,100]},{"t":350,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":391,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":131,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":131,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_error_to_fingerprint_270.json b/packages/SystemUI/res/raw/biometricprompt_sfps_error_to_fingerprint_270.json
new file mode 100644
index 0000000..477c489
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_error_to_fingerprint_270.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":240,"op":421,"w":150,"h":150,"nm":"BM_Prompt_Error-to-FP_270","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":170,"s":[43.5,43.5,100]},{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":240,"s":[43.5,43.5,100]},{"t":260,"s":[64,64,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red400","cl":"red400","parent":4,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.484,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.91,0.191,0],"ix":1,"l":2},"s":{"a":0,"k":[229.885,229.885,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[4,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,-7.079],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".red400","cl":"red400","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.889,9.487,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.889,7.487,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":[4,4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,7.491],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".red400","cl":"red400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":270,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.933333333333,0.403921568627,0.360784313725,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Matte 3","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Nail 2","parent":11,"tt":1,"tp":8,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Matte 2","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"tp":10,"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":320,"s":[43]},{"t":365,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":320,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":365,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Nail","parent":15,"tt":1,"tp":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":14,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":320,"s":[50]},{"t":390,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":290,"s":[0,0,100]},{"t":380,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":290,"op":391,"st":290,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":290,"s":[50]},{"t":360,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":260,"s":[0,0,100]},{"t":350,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":391,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":131,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":131,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_error_to_fingerprint_90.json b/packages/SystemUI/res/raw/biometricprompt_sfps_error_to_fingerprint_90.json
new file mode 100644
index 0000000..9e6b422
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_error_to_fingerprint_90.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":240,"op":421,"w":150,"h":150,"nm":"BM_Prompt_Error-to-FP_90","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":170,"s":[43.5,43.5,100]},{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":240,"s":[43.5,43.5,100]},{"t":260,"s":[64,64,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red400","cl":"red400","parent":4,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.484,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.91,0.191,0],"ix":1,"l":2},"s":{"a":0,"k":[229.885,229.885,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[4,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,-7.079],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".red400","cl":"red400","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.889,9.487,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.889,7.487,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":[4,4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,7.491],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".red400","cl":"red400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":90,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.933333333333,0.403921568627,0.360784313725,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Matte 3","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Nail 2","parent":11,"tt":1,"tp":8,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Matte 2","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"tp":10,"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":320,"s":[43]},{"t":365,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":320,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":365,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Nail","parent":15,"tt":1,"tp":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":14,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":320,"s":[50]},{"t":390,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":290,"s":[0,0,100]},{"t":380,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":290,"op":391,"st":290,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":290,"s":[50]},{"t":360,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":260,"s":[0,0,100]},{"t":350,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":391,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":131,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":131,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_error_to_success.json b/packages/SystemUI/res/raw/biometricprompt_sfps_error_to_success.json
new file mode 100644
index 0000000..348e25d
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_error_to_success.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":240,"op":421,"w":150,"h":150,"nm":"Error-to-success","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".red400","cl":"red400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.484,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.91,0.191,0],"ix":1,"l":2},"s":{"a":0,"k":[229.885,229.885,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[4,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,-7.079],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red400","cl":"red400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.889,9.487,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.889,7.487,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":[4,4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,7.491],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".red400","cl":"red400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[43.5,43.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.933333333333,0.403921568627,0.360784313725,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"t":170,"s":[43.5,43.5,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"green400","parent":8,"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":[71.264,71.264,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":[0.356862745098,0.725490196078,0.454901960784,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":240,"s":[0]},{"t":270,"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":240,"op":1131,"st":231,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":".green400","cl":"green400","parent":6,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.356862745098,0.725490196078,0.454901960784,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":6,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":240,"op":982,"st":82,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":".grey400","cl":"grey400","parent":6,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"t":166,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".grey600","cl":"grey600","parent":6,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".grey600","cl":"grey600","parent":6,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Matte","parent":6,"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,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":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Nail","parent":17,"tt":1,"tp":14,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":"Matte","parent":6,"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,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":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":"Finger","parent":6,"tt":1,"tp":16,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".black","cl":"black","parent":6,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":6,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".blue401","cl":"blue401","parent":6,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":930,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":".blue400","cl":"blue400","parent":6,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":".black","cl":"black","parent":6,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_error_to_unlock.json b/packages/SystemUI/res/raw/biometricprompt_sfps_error_to_unlock.json
new file mode 100644
index 0000000..ab52490
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_error_to_unlock.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":240,"op":421,"w":150,"h":150,"nm":"BM_Prompt_Error-to-Unlock_0","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".blue400","cl":"blue400","parent":4,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.4,0.61568627451,0.964705882353,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".blue400","cl":"blue400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[74.259,78.552,0],"ix":2,"l":2},"a":{"a":0,"k":[-5.873,13.309,0],"ix":1,"l":2},"s":{"a":0,"k":[44,44,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.4,"y":0},"t":244,"s":[{"i":[[0,0],[0,0],[0.938,1.057],[1.355,0],[0.938,-1.057],[0,-1.527],[0,0],[-1.512,1.674],[-2.111,0],[-1.512,-1.703],[0,-2.408],[0,0]],"o":[[0,0],[0,-1.527],[-0.938,-1.057],[-1.329,0],[-0.938,1.057],[0,0],[0,-2.408],[1.486,-1.703],[2.137,0],[1.486,1.674],[0,0],[0,0]],"v":[[-0.17,-6.078],[-0.17,-9.822],[-1.577,-13.699],[-5.017,-15.284],[-8.419,-13.699],[-9.826,-9.822],[-12.68,-9.822],[-10.412,-15.945],[-5.017,-18.5],[0.456,-15.945],[2.684,-9.822],[2.684,-6.078]],"c":true}]},{"t":259,"s":[{"i":[[0,0],[0,0],[-1.069,1.057],[-1.545,0],[-1.069,-1.057],[0,-1.527],[0,0],[1.723,1.674],[2.406,0],[1.723,-1.703],[0,-2.408],[0,0]],"o":[[0,0],[0,-1.527],[1.069,-1.057],[1.515,0],[1.069,1.057],[0,0],[0,-2.408],[-1.693,-1.703],[-2.436,0],[-1.693,1.674],[0,0],[0,0]],"v":[[2.74,-6.079],[2.74,-9.823],[4.345,-13.699],[8.266,-15.285],[12.143,-13.699],[13.747,-9.823],[17,-9.823],[14.415,-15.945],[8.266,-18.5],[2.028,-15.945],[-0.512,-9.823],[-0.512,-6.079]],"c":true}]}],"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[214.286,214.286],"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":"icon","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":94,"op":994,"st":94,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".blue400","cl":"blue400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[74.259,78.552,0],"ix":2,"l":2},"a":{"a":0,"k":[-5.873,13.309,0],"ix":1,"l":2},"s":{"a":0,"k":[44,44,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],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[8.266,15.285],[-13.747,15.285],[-13.747,-2.863],[8.266,-2.863]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.683,-0.675],[0.98,0],[0.683,0.675],[0,0.94],[-0.683,0.705],[-0.98,0],[-0.683,-0.705],[0,-0.94]],"o":[[-0.683,0.675],[-0.98,0],[-0.683,-0.675],[0,-0.94],[0.683,-0.705],[0.98,0],[0.683,0.705],[0,0.94]],"v":[[-0.245,8.677],[-2.74,9.69],[-5.236,8.677],[-6.261,6.255],[-5.236,3.788],[-2.74,2.731],[-0.245,3.788],[0.78,6.255]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[-0.624,-0.646],[-0.891,0],[0,0],[-0.624,0.617],[0,0.881],[0,0],[0.654,0.617],[0.891,0],[0,0],[0,0],[0,0],[0.654,-0.646],[0,-0.881],[0,0]],"o":[[0.654,0.617],[0,0],[0.891,0],[0.654,-0.646],[0,0],[0,-0.881],[-0.624,-0.646],[0,0],[0,0],[0,0],[-0.891,0],[-0.624,0.617],[0,0],[0,0.881]],"v":[[-16.064,17.575],[-13.747,18.5],[8.266,18.5],[10.539,17.575],[11.519,15.285],[11.519,-2.863],[10.539,-5.11],[8.266,-6.079],[2.74,-6.079],[-0.512,-6.079],[-13.747,-6.079],[-16.064,-5.11],[-17,-2.863],[-17,15.285]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[214.286,214.286],"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":"icon","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":94,"op":994,"st":94,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[43.5,43.5,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".red400","cl":"red400","parent":7,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.484,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.91,0.191,0],"ix":1,"l":2},"s":{"a":0,"k":[229.885,229.885,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[4,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,-7.079],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".red400","cl":"red400","parent":5,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.889,9.487,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.889,7.487,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":[4,4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,7.491],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".red400","cl":"red400","parent":4,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.933333333333,0.403921568627,0.360784313725,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[{"tm":248,"cm":"","dr":0},{"tm":256,"cm":"","dr":0}]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_authenticating.json b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_authenticating.json
new file mode 100644
index 0000000..9db2543
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_authenticating.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":301,"w":150,"h":150,"nm":"BM_Prompt","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[64,64,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Nail","parent":8,"tt":1,"tp":5,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":7,"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":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":".blue401","cl":"blue401","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":930,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".black","cl":"black","parent":1,"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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_error.json b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_error.json
new file mode 100644
index 0000000..603760f
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_error.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":181,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Error_0and180","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":170,"s":[43.5,43.5,100]},{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":240,"s":[43.5,43.5,100]},{"t":260,"s":[64,64,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red400","cl":"red400","parent":4,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.484,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.91,0.191,0],"ix":1,"l":2},"s":{"a":0,"k":[229.885,229.885,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[4,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,-7.079],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".red400","cl":"red400","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.889,9.487,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.889,7.487,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":[4,4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,7.491],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".red400","cl":"red400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.933333333333,0.403921568627,0.360784313725,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Matte 3","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Nail 2","parent":11,"tt":1,"tp":8,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Matte 2","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"tp":10,"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":320,"s":[43]},{"t":365,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":320,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":365,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Nail","parent":15,"tt":1,"tp":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":14,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":320,"s":[50]},{"t":390,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":290,"s":[0,0,100]},{"t":380,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":290,"op":391,"st":290,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":290,"s":[50]},{"t":360,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":260,"s":[0,0,100]},{"t":350,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":391,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":131,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":131,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_error_180.json b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_error_180.json
new file mode 100755
index 0000000..4e66cfa
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_error_180.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":181,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Error_left","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[-64,64,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":170,"s":[-43.5,43.5,100]},{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":240,"s":[-43.5,43.5,100]},{"t":260,"s":[-64,64,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red400","cl":"red400","parent":4,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.484,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.91,0.191,0],"ix":1,"l":2},"s":{"a":0,"k":[229.885,229.885,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[4,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,-7.079],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".red400","cl":"red400","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.889,9.487,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.889,7.487,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":[4,4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,7.491],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".red400","cl":"red400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.933333333333,0.403921568627,0.360784313725,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Matte 3","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Nail 2","parent":11,"tt":1,"tp":8,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Matte 2","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"tp":10,"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":320,"s":[43]},{"t":365,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":320,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":365,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Nail","parent":15,"tt":1,"tp":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":14,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":320,"s":[50]},{"t":390,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":290,"s":[0,0,100]},{"t":380,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":290,"op":391,"st":290,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":290,"s":[50]},{"t":360,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":260,"s":[0,0,100]},{"t":350,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":391,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":131,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":131,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_error_270.json b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_error_270.json
new file mode 100644
index 0000000..a1d2251
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_error_270.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":181,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Error_270","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":170,"s":[43.5,43.5,100]},{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":240,"s":[43.5,43.5,100]},{"t":260,"s":[64,64,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red400","cl":"red400","parent":4,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.484,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.91,0.191,0],"ix":1,"l":2},"s":{"a":0,"k":[229.885,229.885,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[4,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,-7.079],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".red400","cl":"red400","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.889,9.487,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.889,7.487,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":[4,4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,7.491],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".red400","cl":"red400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":270,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.933333333333,0.403921568627,0.360784313725,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Matte 3","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Nail 2","parent":11,"tt":1,"tp":8,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Matte 2","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"tp":10,"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":320,"s":[43]},{"t":365,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":320,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":365,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Nail","parent":15,"tt":1,"tp":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":14,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":320,"s":[50]},{"t":390,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":290,"s":[0,0,100]},{"t":380,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":290,"op":391,"st":290,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":290,"s":[50]},{"t":360,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":260,"s":[0,0,100]},{"t":350,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":391,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":131,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":131,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_error_90.json b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_error_90.json
new file mode 100644
index 0000000..59dc0d4
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_error_90.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":181,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Error_90","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":170,"s":[43.5,43.5,100]},{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":240,"s":[43.5,43.5,100]},{"t":260,"s":[64,64,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red400","cl":"red400","parent":4,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.484,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.91,0.191,0],"ix":1,"l":2},"s":{"a":0,"k":[229.885,229.885,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[4,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,-7.079],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".red400","cl":"red400","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.889,9.487,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.889,7.487,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":[4,4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,7.491],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".red400","cl":"red400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":90,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.933333333333,0.403921568627,0.360784313725,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Matte 3","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Nail 2","parent":11,"tt":1,"tp":8,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Matte 2","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"tp":10,"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":320,"s":[43]},{"t":365,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":320,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":365,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Nail","parent":15,"tt":1,"tp":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":14,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":320,"s":[50]},{"t":390,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":290,"s":[0,0,100]},{"t":380,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":290,"op":391,"st":290,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":290,"s":[50]},{"t":360,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":260,"s":[0,0,100]},{"t":350,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":391,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":131,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":131,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_success.json b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_success.json
new file mode 100644
index 0000000..e2c8500
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_success.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":211,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Success_0and180","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"t":170,"s":[43.5,43.5,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"green400","parent":3,"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":[71.264,71.264,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":[0.356862745098,0.725490196078,0.454901960784,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":150,"s":[0]},{"t":180,"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":150,"op":1041,"st":141,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green400","cl":"green400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"t":166,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.356862745098,0.725490196078,0.454901960784,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"t":166,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Nail","parent":10,"tt":1,"tp":7,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":9,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":930,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_success_180.json b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_success_180.json
new file mode 100755
index 0000000..21ee20d
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_success_180.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":211,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Success_left","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[-64,64,100]},{"t":170,"s":[-43.5,43.5,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"green400","parent":3,"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":[-71.264,71.264,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":[0.356862745098,0.725490196078,0.454901960784,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":150,"s":[0]},{"t":180,"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":150,"op":1041,"st":141,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green400","cl":"green400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"t":166,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.356862745098,0.725490196078,0.454901960784,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"t":166,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Nail","parent":10,"tt":1,"tp":7,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":9,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":930,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_success_270.json b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_success_270.json
new file mode 100644
index 0000000..4c1a809
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_success_270.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":211,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Success_270","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"t":170,"s":[43.5,43.5,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"green400","parent":3,"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":[71.264,71.264,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":[0.356862745098,0.725490196078,0.454901960784,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":150,"s":[0]},{"t":180,"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":150,"op":1041,"st":141,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green400","cl":"green400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"t":166,"s":[100]}],"ix":11},"r":{"a":0,"k":-90,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.356862745098,0.725490196078,0.454901960784,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"t":166,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Nail","parent":10,"tt":1,"tp":7,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":9,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":930,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_success_90.json b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_success_90.json
new file mode 100644
index 0000000..51e17f7
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_success_90.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":211,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Success_90","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"t":170,"s":[43.5,43.5,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"green400","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":90,"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":[71.264,71.264,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":[0.356862745098,0.725490196078,0.454901960784,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":150,"s":[0]},{"t":180,"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":150,"op":1041,"st":141,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green400","cl":"green400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"t":166,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.356862745098,0.725490196078,0.454901960784,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"t":166,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Nail","parent":10,"tt":1,"tp":7,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":9,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":930,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_unlock.json b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_unlock.json
new file mode 100644
index 0000000..c4db1e4
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_unlock.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":181,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Unlock_0and180","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-1.704,8.166,0],"ix":2,"l":2},"a":{"a":0,"k":[-5.873,13.309,0],"ix":1,"l":2},"s":{"a":0,"k":[101.149,101.149,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.4,"y":0},"t":150,"s":[{"i":[[0,0],[0,0],[0.938,1.057],[1.355,0],[0.938,-1.057],[0,-1.527],[0,0],[-1.512,1.674],[-2.111,0],[-1.512,-1.703],[0,-2.408],[0,0]],"o":[[0,0],[0,-1.527],[-0.938,-1.057],[-1.329,0],[-0.938,1.057],[0,0],[0,-2.408],[1.486,-1.703],[2.137,0],[1.486,1.674],[0,0],[0,0]],"v":[[-0.17,-6.078],[-0.17,-9.822],[-1.577,-13.699],[-5.017,-15.284],[-8.419,-13.699],[-9.826,-9.822],[-12.68,-9.822],[-10.412,-15.945],[-5.017,-18.5],[0.456,-15.945],[2.684,-9.822],[2.684,-6.078]],"c":true}]},{"t":165,"s":[{"i":[[0,0],[0,0],[-1.069,1.057],[-1.545,0],[-1.069,-1.057],[0,-1.527],[0,0],[1.723,1.674],[2.406,0],[1.723,-1.703],[0,-2.408],[0,0]],"o":[[0,0],[0,-1.527],[1.069,-1.057],[1.515,0],[1.069,1.057],[0,0],[0,-2.408],[-1.693,-1.703],[-2.436,0],[-1.693,1.674],[0,0],[0,0]],"v":[[2.74,-6.079],[2.74,-9.823],[4.345,-13.699],[8.266,-15.285],[12.143,-13.699],[13.747,-9.823],[17,-9.823],[14.415,-15.945],[8.266,-18.5],[2.028,-15.945],[-0.512,-9.823],[-0.512,-6.079]],"c":true}]}],"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[214.286,214.286],"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":"icon","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-1.704,8.166,0],"ix":2,"l":2},"a":{"a":0,"k":[-5.873,13.309,0],"ix":1,"l":2},"s":{"a":0,"k":[101.149,101.149,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],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[8.266,15.285],[-13.747,15.285],[-13.747,-2.863],[8.266,-2.863]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.683,-0.675],[0.98,0],[0.683,0.675],[0,0.94],[-0.683,0.705],[-0.98,0],[-0.683,-0.705],[0,-0.94]],"o":[[-0.683,0.675],[-0.98,0],[-0.683,-0.675],[0,-0.94],[0.683,-0.705],[0.98,0],[0.683,0.705],[0,0.94]],"v":[[-0.245,8.677],[-2.74,9.69],[-5.236,8.677],[-6.261,6.255],[-5.236,3.788],[-2.74,2.731],[-0.245,3.788],[0.78,6.255]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[-0.624,-0.646],[-0.891,0],[0,0],[-0.624,0.617],[0,0.881],[0,0],[0.654,0.617],[0.891,0],[0,0],[0,0],[0,0],[0.654,-0.646],[0,-0.881],[0,0]],"o":[[0.654,0.617],[0,0],[0.891,0],[0.654,-0.646],[0,0],[0,-0.881],[-0.624,-0.646],[0,0],[0,0],[0,0],[-0.891,0],[-0.624,0.617],[0,0],[0,0.881]],"v":[[-16.064,17.575],[-13.747,18.5],[8.266,18.5],[10.539,17.575],[11.519,15.285],[11.519,-2.863],[10.539,-5.11],[8.266,-6.079],[2.74,-6.079],[-0.512,-6.079],[-13.747,-6.079],[-16.064,-5.11],[-17,-2.863],[-17,15.285]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[214.286,214.286],"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":"icon","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"t":170,"s":[43.5,43.5,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"green400","parent":5,"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":[71.264,71.264,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":[0.356862745098,0.725490196078,0.454901960784,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":240,"s":[0]},{"t":270,"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":240,"op":1131,"st":231,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".green400","cl":"green400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.356862745098,0.725490196078,0.454901960784,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":6,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":240,"op":982,"st":82,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.4,0.61568627451,0.964705882353,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":".grey400","cl":"grey400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"t":166,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":".grey600","cl":"grey600","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".grey600","cl":"grey600","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Matte","parent":3,"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,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":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Nail","parent":14,"tt":1,"tp":11,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Matte","parent":3,"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,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":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Finger","parent":3,"tt":1,"tp":13,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".black","cl":"black","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":930,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".black","cl":"black","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_unlock_180.json b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_unlock_180.json
new file mode 100755
index 0000000..56cd2ad
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_unlock_180.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":181,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Unlock_left","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1.704,8.166,0],"ix":2,"l":2},"a":{"a":0,"k":[-5.873,13.309,0],"ix":1,"l":2},"s":{"a":0,"k":[-101.149,101.149,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.4,"y":0},"t":150,"s":[{"i":[[0,0],[0,0],[0.938,1.057],[1.355,0],[0.938,-1.057],[0,-1.527],[0,0],[-1.512,1.674],[-2.111,0],[-1.512,-1.703],[0,-2.408],[0,0]],"o":[[0,0],[0,-1.527],[-0.938,-1.057],[-1.329,0],[-0.938,1.057],[0,0],[0,-2.408],[1.486,-1.703],[2.137,0],[1.486,1.674],[0,0],[0,0]],"v":[[-0.17,-6.078],[-0.17,-9.822],[-1.577,-13.699],[-5.017,-15.284],[-8.419,-13.699],[-9.826,-9.822],[-12.68,-9.822],[-10.412,-15.945],[-5.017,-18.5],[0.456,-15.945],[2.684,-9.822],[2.684,-6.078]],"c":true}]},{"t":165,"s":[{"i":[[0,0],[0,0],[-1.069,1.057],[-1.545,0],[-1.069,-1.057],[0,-1.527],[0,0],[1.723,1.674],[2.406,0],[1.723,-1.703],[0,-2.408],[0,0]],"o":[[0,0],[0,-1.527],[1.069,-1.057],[1.515,0],[1.069,1.057],[0,0],[0,-2.408],[-1.693,-1.703],[-2.436,0],[-1.693,1.674],[0,0],[0,0]],"v":[[2.74,-6.079],[2.74,-9.823],[4.345,-13.699],[8.266,-15.285],[12.143,-13.699],[13.747,-9.823],[17,-9.823],[14.415,-15.945],[8.266,-18.5],[2.028,-15.945],[-0.512,-9.823],[-0.512,-6.079]],"c":true}]}],"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[214.286,214.286],"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":"icon","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1.704,8.166,0],"ix":2,"l":2},"a":{"a":0,"k":[-5.873,13.309,0],"ix":1,"l":2},"s":{"a":0,"k":[-101.149,101.149,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],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[8.266,15.285],[-13.747,15.285],[-13.747,-2.863],[8.266,-2.863]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.683,-0.675],[0.98,0],[0.683,0.675],[0,0.94],[-0.683,0.705],[-0.98,0],[-0.683,-0.705],[0,-0.94]],"o":[[-0.683,0.675],[-0.98,0],[-0.683,-0.675],[0,-0.94],[0.683,-0.705],[0.98,0],[0.683,0.705],[0,0.94]],"v":[[-0.245,8.677],[-2.74,9.69],[-5.236,8.677],[-6.261,6.255],[-5.236,3.788],[-2.74,2.731],[-0.245,3.788],[0.78,6.255]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[-0.624,-0.646],[-0.891,0],[0,0],[-0.624,0.617],[0,0.881],[0,0],[0.654,0.617],[0.891,0],[0,0],[0,0],[0,0],[0.654,-0.646],[0,-0.881],[0,0]],"o":[[0.654,0.617],[0,0],[0.891,0],[0.654,-0.646],[0,0],[0,-0.881],[-0.624,-0.646],[0,0],[0,0],[0,0],[-0.891,0],[-0.624,0.617],[0,0],[0,0.881]],"v":[[-16.064,17.575],[-13.747,18.5],[8.266,18.5],[10.539,17.575],[11.519,15.285],[11.519,-2.863],[10.539,-5.11],[8.266,-6.079],[2.74,-6.079],[-0.512,-6.079],[-13.747,-6.079],[-16.064,-5.11],[-17,-2.863],[-17,15.285]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[214.286,214.286],"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":"icon","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[-64,64,100]},{"t":170,"s":[-43.5,43.5,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"green400","parent":5,"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":[71.264,71.264,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":[0.356862745098,0.725490196078,0.454901960784,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":240,"s":[0]},{"t":270,"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":240,"op":1131,"st":231,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".green400","cl":"green400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.356862745098,0.725490196078,0.454901960784,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":6,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":240,"op":982,"st":82,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.4,0.61568627451,0.964705882353,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":".grey400","cl":"grey400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"t":166,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":".grey600","cl":"grey600","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".grey600","cl":"grey600","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Matte","parent":3,"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,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":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Nail","parent":14,"tt":1,"tp":11,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Matte","parent":3,"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,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":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Finger","parent":3,"tt":1,"tp":13,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".black","cl":"black","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":930,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".black","cl":"black","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_unlock_270.json b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_unlock_270.json
new file mode 100644
index 0000000..30bb2d9
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_unlock_270.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":181,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Unlock_270","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[8.166,1.704,0],"ix":2,"l":2},"a":{"a":0,"k":[-5.873,13.309,0],"ix":1,"l":2},"s":{"a":0,"k":[101.149,101.149,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.4,"y":0},"t":150,"s":[{"i":[[0,0],[0,0],[0.938,1.057],[1.355,0],[0.938,-1.057],[0,-1.527],[0,0],[-1.512,1.674],[-2.111,0],[-1.512,-1.703],[0,-2.408],[0,0]],"o":[[0,0],[0,-1.527],[-0.938,-1.057],[-1.329,0],[-0.938,1.057],[0,0],[0,-2.408],[1.486,-1.703],[2.137,0],[1.486,1.674],[0,0],[0,0]],"v":[[-0.17,-6.078],[-0.17,-9.822],[-1.577,-13.699],[-5.017,-15.284],[-8.419,-13.699],[-9.826,-9.822],[-12.68,-9.822],[-10.412,-15.945],[-5.017,-18.5],[0.456,-15.945],[2.684,-9.822],[2.684,-6.078]],"c":true}]},{"t":165,"s":[{"i":[[0,0],[0,0],[-1.069,1.057],[-1.545,0],[-1.069,-1.057],[0,-1.527],[0,0],[1.723,1.674],[2.406,0],[1.723,-1.703],[0,-2.408],[0,0]],"o":[[0,0],[0,-1.527],[1.069,-1.057],[1.515,0],[1.069,1.057],[0,0],[0,-2.408],[-1.693,-1.703],[-2.436,0],[-1.693,1.674],[0,0],[0,0]],"v":[[2.74,-6.079],[2.74,-9.823],[4.345,-13.699],[8.266,-15.285],[12.143,-13.699],[13.747,-9.823],[17,-9.823],[14.415,-15.945],[8.266,-18.5],[2.028,-15.945],[-0.512,-9.823],[-0.512,-6.079]],"c":true}]}],"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[214.286,214.286],"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":"icon","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[8.166,1.704,0],"ix":2,"l":2},"a":{"a":0,"k":[-5.873,13.309,0],"ix":1,"l":2},"s":{"a":0,"k":[101.149,101.149,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],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[8.266,15.285],[-13.747,15.285],[-13.747,-2.863],[8.266,-2.863]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.683,-0.675],[0.98,0],[0.683,0.675],[0,0.94],[-0.683,0.705],[-0.98,0],[-0.683,-0.705],[0,-0.94]],"o":[[-0.683,0.675],[-0.98,0],[-0.683,-0.675],[0,-0.94],[0.683,-0.705],[0.98,0],[0.683,0.705],[0,0.94]],"v":[[-0.245,8.677],[-2.74,9.69],[-5.236,8.677],[-6.261,6.255],[-5.236,3.788],[-2.74,2.731],[-0.245,3.788],[0.78,6.255]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[-0.624,-0.646],[-0.891,0],[0,0],[-0.624,0.617],[0,0.881],[0,0],[0.654,0.617],[0.891,0],[0,0],[0,0],[0,0],[0.654,-0.646],[0,-0.881],[0,0]],"o":[[0.654,0.617],[0,0],[0.891,0],[0.654,-0.646],[0,0],[0,-0.881],[-0.624,-0.646],[0,0],[0,0],[0,0],[-0.891,0],[-0.624,0.617],[0,0],[0,0.881]],"v":[[-16.064,17.575],[-13.747,18.5],[8.266,18.5],[10.539,17.575],[11.519,15.285],[11.519,-2.863],[10.539,-5.11],[8.266,-6.079],[2.74,-6.079],[-0.512,-6.079],[-13.747,-6.079],[-16.064,-5.11],[-17,-2.863],[-17,15.285]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[214.286,214.286],"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":"icon","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"t":170,"s":[43.5,43.5,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"green400","parent":5,"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":[71.264,71.264,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":[0.356862745098,0.725490196078,0.454901960784,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":240,"s":[0]},{"t":270,"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":240,"op":1131,"st":231,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".green400","cl":"green400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.356862745098,0.725490196078,0.454901960784,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":6,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":240,"op":982,"st":82,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.4,0.61568627451,0.964705882353,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":".grey400","cl":"grey400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"t":166,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":".grey600","cl":"grey600","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".grey600","cl":"grey600","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Matte","parent":3,"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,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":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Nail","parent":14,"tt":1,"tp":11,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Matte","parent":3,"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,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":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Finger","parent":3,"tt":1,"tp":13,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".black","cl":"black","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":930,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".black","cl":"black","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_unlock_90.json b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_unlock_90.json
new file mode 100644
index 0000000..f9d13a6
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_fingerprint_to_unlock_90.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":181,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Unlock_90","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[-8.166,-1.704,0],"ix":2,"l":2},"a":{"a":0,"k":[-5.873,13.309,0],"ix":1,"l":2},"s":{"a":0,"k":[101.149,101.149,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.4,"y":0},"t":150,"s":[{"i":[[0,0],[0,0],[0.938,1.057],[1.355,0],[0.938,-1.057],[0,-1.527],[0,0],[-1.512,1.674],[-2.111,0],[-1.512,-1.703],[0,-2.408],[0,0]],"o":[[0,0],[0,-1.527],[-0.938,-1.057],[-1.329,0],[-0.938,1.057],[0,0],[0,-2.408],[1.486,-1.703],[2.137,0],[1.486,1.674],[0,0],[0,0]],"v":[[-0.17,-6.078],[-0.17,-9.822],[-1.577,-13.699],[-5.017,-15.284],[-8.419,-13.699],[-9.826,-9.822],[-12.68,-9.822],[-10.412,-15.945],[-5.017,-18.5],[0.456,-15.945],[2.684,-9.822],[2.684,-6.078]],"c":true}]},{"t":165,"s":[{"i":[[0,0],[0,0],[-1.069,1.057],[-1.545,0],[-1.069,-1.057],[0,-1.527],[0,0],[1.723,1.674],[2.406,0],[1.723,-1.703],[0,-2.408],[0,0]],"o":[[0,0],[0,-1.527],[1.069,-1.057],[1.515,0],[1.069,1.057],[0,0],[0,-2.408],[-1.693,-1.703],[-2.436,0],[-1.693,1.674],[0,0],[0,0]],"v":[[2.74,-6.079],[2.74,-9.823],[4.345,-13.699],[8.266,-15.285],[12.143,-13.699],[13.747,-9.823],[17,-9.823],[14.415,-15.945],[8.266,-18.5],[2.028,-15.945],[-0.512,-9.823],[-0.512,-6.079]],"c":true}]}],"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[214.286,214.286],"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":"icon","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[-8.166,-1.704,0],"ix":2,"l":2},"a":{"a":0,"k":[-5.873,13.309,0],"ix":1,"l":2},"s":{"a":0,"k":[101.149,101.149,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],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[8.266,15.285],[-13.747,15.285],[-13.747,-2.863],[8.266,-2.863]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.683,-0.675],[0.98,0],[0.683,0.675],[0,0.94],[-0.683,0.705],[-0.98,0],[-0.683,-0.705],[0,-0.94]],"o":[[-0.683,0.675],[-0.98,0],[-0.683,-0.675],[0,-0.94],[0.683,-0.705],[0.98,0],[0.683,0.705],[0,0.94]],"v":[[-0.245,8.677],[-2.74,9.69],[-5.236,8.677],[-6.261,6.255],[-5.236,3.788],[-2.74,2.731],[-0.245,3.788],[0.78,6.255]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[-0.624,-0.646],[-0.891,0],[0,0],[-0.624,0.617],[0,0.881],[0,0],[0.654,0.617],[0.891,0],[0,0],[0,0],[0,0],[0.654,-0.646],[0,-0.881],[0,0]],"o":[[0.654,0.617],[0,0],[0.891,0],[0.654,-0.646],[0,0],[0,-0.881],[-0.624,-0.646],[0,0],[0,0],[0,0],[-0.891,0],[-0.624,0.617],[0,0],[0,0.881]],"v":[[-16.064,17.575],[-13.747,18.5],[8.266,18.5],[10.539,17.575],[11.519,15.285],[11.519,-2.863],[10.539,-5.11],[8.266,-6.079],[2.74,-6.079],[-0.512,-6.079],[-13.747,-6.079],[-16.064,-5.11],[-17,-2.863],[-17,15.285]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[214.286,214.286],"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":"icon","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"t":170,"s":[43.5,43.5,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"green400","parent":5,"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":[71.264,71.264,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":[0.356862745098,0.725490196078,0.454901960784,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":240,"s":[0]},{"t":270,"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":240,"op":1131,"st":231,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".green400","cl":"green400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.356862745098,0.725490196078,0.454901960784,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":6,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":240,"op":982,"st":82,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.4,0.61568627451,0.964705882353,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":".grey400","cl":"grey400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"t":166,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":".grey600","cl":"grey600","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".grey600","cl":"grey600","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Matte","parent":3,"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,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":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Nail","parent":14,"tt":1,"tp":11,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Matte","parent":3,"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,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":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Finger","parent":3,"tt":1,"tp":13,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".black","cl":"black","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":930,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".black","cl":"black","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_error_to_fingerprint.json b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_error_to_fingerprint.json
new file mode 100644
index 0000000..688ed7b
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_error_to_fingerprint.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":240,"op":421,"w":150,"h":150,"nm":"BM_Prompt_Error-to-FP_left","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[-64,64,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":170,"s":[-43.5,43.5,100]},{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":240,"s":[-43.5,43.5,100]},{"t":260,"s":[-64,64,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red400","cl":"red400","parent":4,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.484,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.91,0.191,0],"ix":1,"l":2},"s":{"a":0,"k":[229.885,229.885,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[4,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,-7.079],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".red400","cl":"red400","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.889,9.487,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.889,7.487,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":[4,4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,7.491],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".red400","cl":"red400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.933333333333,0.403921568627,0.360784313725,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Matte 3","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Nail 2","parent":11,"tt":1,"tp":8,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Matte 2","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"tp":10,"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":320,"s":[43]},{"t":365,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":320,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":365,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Nail","parent":15,"tt":1,"tp":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":14,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":320,"s":[50]},{"t":390,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":290,"s":[0,0,100]},{"t":380,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":290,"op":391,"st":290,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":290,"s":[50]},{"t":360,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":260,"s":[0,0,100]},{"t":350,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":391,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":131,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":131,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_error_to_fingerprint_180.json b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_error_to_fingerprint_180.json
new file mode 100644
index 0000000..fa6fc07
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_error_to_fingerprint_180.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":240,"op":421,"w":150,"h":150,"nm":"BM_Prompt_Error-to-FP_0and180","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":170,"s":[43.5,43.5,100]},{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":240,"s":[43.5,43.5,100]},{"t":260,"s":[64,64,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red400","cl":"red400","parent":4,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.484,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.91,0.191,0],"ix":1,"l":2},"s":{"a":0,"k":[229.885,229.885,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[4,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,-7.079],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".red400","cl":"red400","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.889,9.487,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.889,7.487,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":[4,4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,7.491],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".red400","cl":"red400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.933333333333,0.403921568627,0.360784313725,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Matte 3","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Nail 2","parent":11,"tt":1,"tp":8,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Matte 2","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"tp":10,"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":320,"s":[43]},{"t":365,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":320,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":365,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Nail","parent":15,"tt":1,"tp":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":14,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":320,"s":[50]},{"t":390,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":290,"s":[0,0,100]},{"t":380,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":290,"op":391,"st":290,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":290,"s":[50]},{"t":360,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":260,"s":[0,0,100]},{"t":350,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":391,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":131,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":131,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_error_to_fingerprint_270.json b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_error_to_fingerprint_270.json
new file mode 100644
index 0000000..9e6b422
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_error_to_fingerprint_270.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":240,"op":421,"w":150,"h":150,"nm":"BM_Prompt_Error-to-FP_90","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":170,"s":[43.5,43.5,100]},{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":240,"s":[43.5,43.5,100]},{"t":260,"s":[64,64,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red400","cl":"red400","parent":4,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.484,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.91,0.191,0],"ix":1,"l":2},"s":{"a":0,"k":[229.885,229.885,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[4,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,-7.079],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".red400","cl":"red400","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.889,9.487,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.889,7.487,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":[4,4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,7.491],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".red400","cl":"red400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":90,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.933333333333,0.403921568627,0.360784313725,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Matte 3","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Nail 2","parent":11,"tt":1,"tp":8,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Matte 2","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"tp":10,"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":320,"s":[43]},{"t":365,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":320,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":365,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Nail","parent":15,"tt":1,"tp":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":14,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":320,"s":[50]},{"t":390,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":290,"s":[0,0,100]},{"t":380,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":290,"op":391,"st":290,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":290,"s":[50]},{"t":360,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":260,"s":[0,0,100]},{"t":350,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":391,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":131,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":131,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_error_to_fingerprint_90.json b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_error_to_fingerprint_90.json
new file mode 100644
index 0000000..477c489
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_error_to_fingerprint_90.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":240,"op":421,"w":150,"h":150,"nm":"BM_Prompt_Error-to-FP_270","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":170,"s":[43.5,43.5,100]},{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":240,"s":[43.5,43.5,100]},{"t":260,"s":[64,64,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red400","cl":"red400","parent":4,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.484,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.91,0.191,0],"ix":1,"l":2},"s":{"a":0,"k":[229.885,229.885,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[4,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,-7.079],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".red400","cl":"red400","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.889,9.487,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.889,7.487,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":[4,4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,7.491],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".red400","cl":"red400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":270,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.933333333333,0.403921568627,0.360784313725,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Matte 3","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Nail 2","parent":11,"tt":1,"tp":8,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Matte 2","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"tp":10,"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":320,"s":[43]},{"t":365,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":320,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":365,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Nail","parent":15,"tt":1,"tp":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":14,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":320,"s":[50]},{"t":390,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":290,"s":[0,0,100]},{"t":380,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":290,"op":391,"st":290,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":290,"s":[50]},{"t":360,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":260,"s":[0,0,100]},{"t":350,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":391,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":131,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":131,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_authenticating.json b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_authenticating.json
new file mode 100755
index 0000000..c688037
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_authenticating.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":301,"w":150,"h":150,"nm":"BM_Prompt_180","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[-64,64,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Nail","parent":8,"tt":1,"tp":5,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":7,"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":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":".blue401","cl":"blue401","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":930,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".black","cl":"black","parent":1,"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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_error.json b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_error.json
new file mode 100644
index 0000000..4e66cfa
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_error.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":181,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Error_left","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[-64,64,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":170,"s":[-43.5,43.5,100]},{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":240,"s":[-43.5,43.5,100]},{"t":260,"s":[-64,64,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red400","cl":"red400","parent":4,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.484,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.91,0.191,0],"ix":1,"l":2},"s":{"a":0,"k":[229.885,229.885,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[4,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,-7.079],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".red400","cl":"red400","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.889,9.487,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.889,7.487,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":[4,4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,7.491],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".red400","cl":"red400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.933333333333,0.403921568627,0.360784313725,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Matte 3","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Nail 2","parent":11,"tt":1,"tp":8,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Matte 2","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"tp":10,"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":320,"s":[43]},{"t":365,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":320,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":365,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Nail","parent":15,"tt":1,"tp":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":14,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":320,"s":[50]},{"t":390,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":290,"s":[0,0,100]},{"t":380,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":290,"op":391,"st":290,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":290,"s":[50]},{"t":360,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":260,"s":[0,0,100]},{"t":350,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":391,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":131,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":131,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_error_180.json b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_error_180.json
new file mode 100644
index 0000000..603760f
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_error_180.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":181,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Error_0and180","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":170,"s":[43.5,43.5,100]},{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":240,"s":[43.5,43.5,100]},{"t":260,"s":[64,64,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red400","cl":"red400","parent":4,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.484,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.91,0.191,0],"ix":1,"l":2},"s":{"a":0,"k":[229.885,229.885,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[4,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,-7.079],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".red400","cl":"red400","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.889,9.487,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.889,7.487,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":[4,4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,7.491],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".red400","cl":"red400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.933333333333,0.403921568627,0.360784313725,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Matte 3","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Nail 2","parent":11,"tt":1,"tp":8,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Matte 2","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"tp":10,"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":320,"s":[43]},{"t":365,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":320,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":365,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Nail","parent":15,"tt":1,"tp":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":14,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":320,"s":[50]},{"t":390,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":290,"s":[0,0,100]},{"t":380,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":290,"op":391,"st":290,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":290,"s":[50]},{"t":360,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":260,"s":[0,0,100]},{"t":350,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":391,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":131,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":131,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_error_270.json b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_error_270.json
new file mode 100644
index 0000000..59dc0d4
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_error_270.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":181,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Error_90","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":170,"s":[43.5,43.5,100]},{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":240,"s":[43.5,43.5,100]},{"t":260,"s":[64,64,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red400","cl":"red400","parent":4,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.484,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.91,0.191,0],"ix":1,"l":2},"s":{"a":0,"k":[229.885,229.885,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[4,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,-7.079],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".red400","cl":"red400","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.889,9.487,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.889,7.487,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":[4,4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,7.491],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".red400","cl":"red400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":90,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.933333333333,0.403921568627,0.360784313725,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Matte 3","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Nail 2","parent":11,"tt":1,"tp":8,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Matte 2","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"tp":10,"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":320,"s":[43]},{"t":365,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":320,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":365,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Nail","parent":15,"tt":1,"tp":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":14,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":320,"s":[50]},{"t":390,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":290,"s":[0,0,100]},{"t":380,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":290,"op":391,"st":290,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":290,"s":[50]},{"t":360,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":260,"s":[0,0,100]},{"t":350,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":391,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":131,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":131,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_error_90.json b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_error_90.json
new file mode 100644
index 0000000..a1d2251
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_error_90.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":181,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Error_270","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":170,"s":[43.5,43.5,100]},{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":240,"s":[43.5,43.5,100]},{"t":260,"s":[64,64,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red400","cl":"red400","parent":4,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.484,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.91,0.191,0],"ix":1,"l":2},"s":{"a":0,"k":[229.885,229.885,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[4,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,-7.079],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".red400","cl":"red400","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.889,9.487,0],"ix":2,"l":2},"a":{"a":0,"k":[-3.889,7.487,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":[4,4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333396912,0.403921604156,0.360784322023,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":[-3.91,7.491],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".red400","cl":"red400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":270,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.933333333333,0.403921568627,0.360784313725,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":170,"s":[6]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":240,"s":[6]},{"t":260,"s":[4]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Matte 3","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Nail 2","parent":11,"tt":1,"tp":8,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Matte 2","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"tp":10,"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":320,"s":[43]},{"t":365,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":320,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":365,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":428,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Nail","parent":15,"tt":1,"tp":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":14,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":159,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":320,"s":[50]},{"t":390,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":290,"s":[0,0,100]},{"t":380,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":290,"op":391,"st":290,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":290,"s":[50]},{"t":360,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":260,"s":[0,0,100]},{"t":350,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":260,"op":391,"st":260,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":131,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":131,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":248,"s":[0]},{"t":256,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_success.json b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_success.json
new file mode 100644
index 0000000..21ee20d
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_success.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":211,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Success_left","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[-64,64,100]},{"t":170,"s":[-43.5,43.5,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"green400","parent":3,"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":[-71.264,71.264,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":[0.356862745098,0.725490196078,0.454901960784,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":150,"s":[0]},{"t":180,"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":150,"op":1041,"st":141,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green400","cl":"green400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"t":166,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.356862745098,0.725490196078,0.454901960784,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"t":166,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Nail","parent":10,"tt":1,"tp":7,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":9,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":930,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_success_180.json b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_success_180.json
new file mode 100644
index 0000000..e2c8500
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_success_180.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":211,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Success_0and180","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"t":170,"s":[43.5,43.5,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"green400","parent":3,"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":[71.264,71.264,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":[0.356862745098,0.725490196078,0.454901960784,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":150,"s":[0]},{"t":180,"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":150,"op":1041,"st":141,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green400","cl":"green400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"t":166,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.356862745098,0.725490196078,0.454901960784,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"t":166,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Nail","parent":10,"tt":1,"tp":7,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":9,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":930,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_success_270.json b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_success_270.json
new file mode 100644
index 0000000..51e17f7
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_success_270.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":211,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Success_90","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"t":170,"s":[43.5,43.5,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"green400","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":90,"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":[71.264,71.264,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":[0.356862745098,0.725490196078,0.454901960784,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":150,"s":[0]},{"t":180,"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":150,"op":1041,"st":141,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green400","cl":"green400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"t":166,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.356862745098,0.725490196078,0.454901960784,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"t":166,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Nail","parent":10,"tt":1,"tp":7,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":9,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":930,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_success_90.json b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_success_90.json
new file mode 100644
index 0000000..4c1a809
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_success_90.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":211,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Success_270","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"t":170,"s":[43.5,43.5,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"green400","parent":3,"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":[71.264,71.264,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":[0.356862745098,0.725490196078,0.454901960784,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":150,"s":[0]},{"t":180,"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":150,"op":1041,"st":141,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green400","cl":"green400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"t":166,"s":[100]}],"ix":11},"r":{"a":0,"k":-90,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.356862745098,0.725490196078,0.454901960784,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey400","cl":"grey400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"t":166,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".grey600","cl":"grey600","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Nail","parent":10,"tt":1,"tp":7,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Matte","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":[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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Finger","parent":1,"tt":1,"tp":9,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.833,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":930,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".blue400","cl":"blue400","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".black","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_unlock.json b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_unlock.json
new file mode 100644
index 0000000..56cd2ad
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_unlock.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":181,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Unlock_left","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1.704,8.166,0],"ix":2,"l":2},"a":{"a":0,"k":[-5.873,13.309,0],"ix":1,"l":2},"s":{"a":0,"k":[-101.149,101.149,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.4,"y":0},"t":150,"s":[{"i":[[0,0],[0,0],[0.938,1.057],[1.355,0],[0.938,-1.057],[0,-1.527],[0,0],[-1.512,1.674],[-2.111,0],[-1.512,-1.703],[0,-2.408],[0,0]],"o":[[0,0],[0,-1.527],[-0.938,-1.057],[-1.329,0],[-0.938,1.057],[0,0],[0,-2.408],[1.486,-1.703],[2.137,0],[1.486,1.674],[0,0],[0,0]],"v":[[-0.17,-6.078],[-0.17,-9.822],[-1.577,-13.699],[-5.017,-15.284],[-8.419,-13.699],[-9.826,-9.822],[-12.68,-9.822],[-10.412,-15.945],[-5.017,-18.5],[0.456,-15.945],[2.684,-9.822],[2.684,-6.078]],"c":true}]},{"t":165,"s":[{"i":[[0,0],[0,0],[-1.069,1.057],[-1.545,0],[-1.069,-1.057],[0,-1.527],[0,0],[1.723,1.674],[2.406,0],[1.723,-1.703],[0,-2.408],[0,0]],"o":[[0,0],[0,-1.527],[1.069,-1.057],[1.515,0],[1.069,1.057],[0,0],[0,-2.408],[-1.693,-1.703],[-2.436,0],[-1.693,1.674],[0,0],[0,0]],"v":[[2.74,-6.079],[2.74,-9.823],[4.345,-13.699],[8.266,-15.285],[12.143,-13.699],[13.747,-9.823],[17,-9.823],[14.415,-15.945],[8.266,-18.5],[2.028,-15.945],[-0.512,-9.823],[-0.512,-6.079]],"c":true}]}],"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[214.286,214.286],"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":"icon","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1.704,8.166,0],"ix":2,"l":2},"a":{"a":0,"k":[-5.873,13.309,0],"ix":1,"l":2},"s":{"a":0,"k":[-101.149,101.149,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],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[8.266,15.285],[-13.747,15.285],[-13.747,-2.863],[8.266,-2.863]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.683,-0.675],[0.98,0],[0.683,0.675],[0,0.94],[-0.683,0.705],[-0.98,0],[-0.683,-0.705],[0,-0.94]],"o":[[-0.683,0.675],[-0.98,0],[-0.683,-0.675],[0,-0.94],[0.683,-0.705],[0.98,0],[0.683,0.705],[0,0.94]],"v":[[-0.245,8.677],[-2.74,9.69],[-5.236,8.677],[-6.261,6.255],[-5.236,3.788],[-2.74,2.731],[-0.245,3.788],[0.78,6.255]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[-0.624,-0.646],[-0.891,0],[0,0],[-0.624,0.617],[0,0.881],[0,0],[0.654,0.617],[0.891,0],[0,0],[0,0],[0,0],[0.654,-0.646],[0,-0.881],[0,0]],"o":[[0.654,0.617],[0,0],[0.891,0],[0.654,-0.646],[0,0],[0,-0.881],[-0.624,-0.646],[0,0],[0,0],[0,0],[-0.891,0],[-0.624,0.617],[0,0],[0,0.881]],"v":[[-16.064,17.575],[-13.747,18.5],[8.266,18.5],[10.539,17.575],[11.519,15.285],[11.519,-2.863],[10.539,-5.11],[8.266,-6.079],[2.74,-6.079],[-0.512,-6.079],[-13.747,-6.079],[-16.064,-5.11],[-17,-2.863],[-17,15.285]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[214.286,214.286],"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":"icon","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[-64,64,100]},{"t":170,"s":[-43.5,43.5,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"green400","parent":5,"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":[71.264,71.264,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":[0.356862745098,0.725490196078,0.454901960784,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":240,"s":[0]},{"t":270,"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":240,"op":1131,"st":231,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".green400","cl":"green400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.356862745098,0.725490196078,0.454901960784,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":6,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":240,"op":982,"st":82,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.4,0.61568627451,0.964705882353,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":".grey400","cl":"grey400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"t":166,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":".grey600","cl":"grey600","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".grey600","cl":"grey600","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Matte","parent":3,"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,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":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Nail","parent":14,"tt":1,"tp":11,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Matte","parent":3,"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,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":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Finger","parent":3,"tt":1,"tp":13,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".black","cl":"black","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":930,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".black","cl":"black","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_unlock_180.json b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_unlock_180.json
new file mode 100644
index 0000000..c4db1e4
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_unlock_180.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":181,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Unlock_0and180","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-1.704,8.166,0],"ix":2,"l":2},"a":{"a":0,"k":[-5.873,13.309,0],"ix":1,"l":2},"s":{"a":0,"k":[101.149,101.149,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.4,"y":0},"t":150,"s":[{"i":[[0,0],[0,0],[0.938,1.057],[1.355,0],[0.938,-1.057],[0,-1.527],[0,0],[-1.512,1.674],[-2.111,0],[-1.512,-1.703],[0,-2.408],[0,0]],"o":[[0,0],[0,-1.527],[-0.938,-1.057],[-1.329,0],[-0.938,1.057],[0,0],[0,-2.408],[1.486,-1.703],[2.137,0],[1.486,1.674],[0,0],[0,0]],"v":[[-0.17,-6.078],[-0.17,-9.822],[-1.577,-13.699],[-5.017,-15.284],[-8.419,-13.699],[-9.826,-9.822],[-12.68,-9.822],[-10.412,-15.945],[-5.017,-18.5],[0.456,-15.945],[2.684,-9.822],[2.684,-6.078]],"c":true}]},{"t":165,"s":[{"i":[[0,0],[0,0],[-1.069,1.057],[-1.545,0],[-1.069,-1.057],[0,-1.527],[0,0],[1.723,1.674],[2.406,0],[1.723,-1.703],[0,-2.408],[0,0]],"o":[[0,0],[0,-1.527],[1.069,-1.057],[1.515,0],[1.069,1.057],[0,0],[0,-2.408],[-1.693,-1.703],[-2.436,0],[-1.693,1.674],[0,0],[0,0]],"v":[[2.74,-6.079],[2.74,-9.823],[4.345,-13.699],[8.266,-15.285],[12.143,-13.699],[13.747,-9.823],[17,-9.823],[14.415,-15.945],[8.266,-18.5],[2.028,-15.945],[-0.512,-9.823],[-0.512,-6.079]],"c":true}]}],"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[214.286,214.286],"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":"icon","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-1.704,8.166,0],"ix":2,"l":2},"a":{"a":0,"k":[-5.873,13.309,0],"ix":1,"l":2},"s":{"a":0,"k":[101.149,101.149,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],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[8.266,15.285],[-13.747,15.285],[-13.747,-2.863],[8.266,-2.863]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.683,-0.675],[0.98,0],[0.683,0.675],[0,0.94],[-0.683,0.705],[-0.98,0],[-0.683,-0.705],[0,-0.94]],"o":[[-0.683,0.675],[-0.98,0],[-0.683,-0.675],[0,-0.94],[0.683,-0.705],[0.98,0],[0.683,0.705],[0,0.94]],"v":[[-0.245,8.677],[-2.74,9.69],[-5.236,8.677],[-6.261,6.255],[-5.236,3.788],[-2.74,2.731],[-0.245,3.788],[0.78,6.255]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[-0.624,-0.646],[-0.891,0],[0,0],[-0.624,0.617],[0,0.881],[0,0],[0.654,0.617],[0.891,0],[0,0],[0,0],[0,0],[0.654,-0.646],[0,-0.881],[0,0]],"o":[[0.654,0.617],[0,0],[0.891,0],[0.654,-0.646],[0,0],[0,-0.881],[-0.624,-0.646],[0,0],[0,0],[0,0],[-0.891,0],[-0.624,0.617],[0,0],[0,0.881]],"v":[[-16.064,17.575],[-13.747,18.5],[8.266,18.5],[10.539,17.575],[11.519,15.285],[11.519,-2.863],[10.539,-5.11],[8.266,-6.079],[2.74,-6.079],[-0.512,-6.079],[-13.747,-6.079],[-16.064,-5.11],[-17,-2.863],[-17,15.285]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[214.286,214.286],"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":"icon","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"t":170,"s":[43.5,43.5,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"green400","parent":5,"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":[71.264,71.264,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":[0.356862745098,0.725490196078,0.454901960784,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":240,"s":[0]},{"t":270,"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":240,"op":1131,"st":231,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".green400","cl":"green400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.356862745098,0.725490196078,0.454901960784,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":6,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":240,"op":982,"st":82,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.4,0.61568627451,0.964705882353,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":".grey400","cl":"grey400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"t":166,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":".grey600","cl":"grey600","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".grey600","cl":"grey600","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Matte","parent":3,"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,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":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Nail","parent":14,"tt":1,"tp":11,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Matte","parent":3,"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,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":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Finger","parent":3,"tt":1,"tp":13,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".black","cl":"black","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":930,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".black","cl":"black","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_unlock_270.json b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_unlock_270.json
new file mode 100644
index 0000000..f9d13a6
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_unlock_270.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":181,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Unlock_90","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[-8.166,-1.704,0],"ix":2,"l":2},"a":{"a":0,"k":[-5.873,13.309,0],"ix":1,"l":2},"s":{"a":0,"k":[101.149,101.149,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.4,"y":0},"t":150,"s":[{"i":[[0,0],[0,0],[0.938,1.057],[1.355,0],[0.938,-1.057],[0,-1.527],[0,0],[-1.512,1.674],[-2.111,0],[-1.512,-1.703],[0,-2.408],[0,0]],"o":[[0,0],[0,-1.527],[-0.938,-1.057],[-1.329,0],[-0.938,1.057],[0,0],[0,-2.408],[1.486,-1.703],[2.137,0],[1.486,1.674],[0,0],[0,0]],"v":[[-0.17,-6.078],[-0.17,-9.822],[-1.577,-13.699],[-5.017,-15.284],[-8.419,-13.699],[-9.826,-9.822],[-12.68,-9.822],[-10.412,-15.945],[-5.017,-18.5],[0.456,-15.945],[2.684,-9.822],[2.684,-6.078]],"c":true}]},{"t":165,"s":[{"i":[[0,0],[0,0],[-1.069,1.057],[-1.545,0],[-1.069,-1.057],[0,-1.527],[0,0],[1.723,1.674],[2.406,0],[1.723,-1.703],[0,-2.408],[0,0]],"o":[[0,0],[0,-1.527],[1.069,-1.057],[1.515,0],[1.069,1.057],[0,0],[0,-2.408],[-1.693,-1.703],[-2.436,0],[-1.693,1.674],[0,0],[0,0]],"v":[[2.74,-6.079],[2.74,-9.823],[4.345,-13.699],[8.266,-15.285],[12.143,-13.699],[13.747,-9.823],[17,-9.823],[14.415,-15.945],[8.266,-18.5],[2.028,-15.945],[-0.512,-9.823],[-0.512,-6.079]],"c":true}]}],"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[214.286,214.286],"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":"icon","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[-8.166,-1.704,0],"ix":2,"l":2},"a":{"a":0,"k":[-5.873,13.309,0],"ix":1,"l":2},"s":{"a":0,"k":[101.149,101.149,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],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[8.266,15.285],[-13.747,15.285],[-13.747,-2.863],[8.266,-2.863]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.683,-0.675],[0.98,0],[0.683,0.675],[0,0.94],[-0.683,0.705],[-0.98,0],[-0.683,-0.705],[0,-0.94]],"o":[[-0.683,0.675],[-0.98,0],[-0.683,-0.675],[0,-0.94],[0.683,-0.705],[0.98,0],[0.683,0.705],[0,0.94]],"v":[[-0.245,8.677],[-2.74,9.69],[-5.236,8.677],[-6.261,6.255],[-5.236,3.788],[-2.74,2.731],[-0.245,3.788],[0.78,6.255]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[-0.624,-0.646],[-0.891,0],[0,0],[-0.624,0.617],[0,0.881],[0,0],[0.654,0.617],[0.891,0],[0,0],[0,0],[0,0],[0.654,-0.646],[0,-0.881],[0,0]],"o":[[0.654,0.617],[0,0],[0.891,0],[0.654,-0.646],[0,0],[0,-0.881],[-0.624,-0.646],[0,0],[0,0],[0,0],[-0.891,0],[-0.624,0.617],[0,0],[0,0.881]],"v":[[-16.064,17.575],[-13.747,18.5],[8.266,18.5],[10.539,17.575],[11.519,15.285],[11.519,-2.863],[10.539,-5.11],[8.266,-6.079],[2.74,-6.079],[-0.512,-6.079],[-13.747,-6.079],[-16.064,-5.11],[-17,-2.863],[-17,15.285]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[214.286,214.286],"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":"icon","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"t":170,"s":[43.5,43.5,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"green400","parent":5,"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":[71.264,71.264,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":[0.356862745098,0.725490196078,0.454901960784,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":240,"s":[0]},{"t":270,"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":240,"op":1131,"st":231,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".green400","cl":"green400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.356862745098,0.725490196078,0.454901960784,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":6,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":240,"op":982,"st":82,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.4,0.61568627451,0.964705882353,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":".grey400","cl":"grey400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"t":166,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":".grey600","cl":"grey600","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".grey600","cl":"grey600","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Matte","parent":3,"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,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":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Nail","parent":14,"tt":1,"tp":11,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Matte","parent":3,"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,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":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Finger","parent":3,"tt":1,"tp":13,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".black","cl":"black","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":930,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".black","cl":"black","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_unlock_90.json b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_unlock_90.json
new file mode 100644
index 0000000..30bb2d9
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_rear_display_fingerprint_to_unlock_90.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":181,"w":150,"h":150,"nm":"BM_Prompt_FP-to-Unlock_270","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[8.166,1.704,0],"ix":2,"l":2},"a":{"a":0,"k":[-5.873,13.309,0],"ix":1,"l":2},"s":{"a":0,"k":[101.149,101.149,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.4,"y":0},"t":150,"s":[{"i":[[0,0],[0,0],[0.938,1.057],[1.355,0],[0.938,-1.057],[0,-1.527],[0,0],[-1.512,1.674],[-2.111,0],[-1.512,-1.703],[0,-2.408],[0,0]],"o":[[0,0],[0,-1.527],[-0.938,-1.057],[-1.329,0],[-0.938,1.057],[0,0],[0,-2.408],[1.486,-1.703],[2.137,0],[1.486,1.674],[0,0],[0,0]],"v":[[-0.17,-6.078],[-0.17,-9.822],[-1.577,-13.699],[-5.017,-15.284],[-8.419,-13.699],[-9.826,-9.822],[-12.68,-9.822],[-10.412,-15.945],[-5.017,-18.5],[0.456,-15.945],[2.684,-9.822],[2.684,-6.078]],"c":true}]},{"t":165,"s":[{"i":[[0,0],[0,0],[-1.069,1.057],[-1.545,0],[-1.069,-1.057],[0,-1.527],[0,0],[1.723,1.674],[2.406,0],[1.723,-1.703],[0,-2.408],[0,0]],"o":[[0,0],[0,-1.527],[1.069,-1.057],[1.515,0],[1.069,1.057],[0,0],[0,-2.408],[-1.693,-1.703],[-2.436,0],[-1.693,1.674],[0,0],[0,0]],"v":[[2.74,-6.079],[2.74,-9.823],[4.345,-13.699],[8.266,-15.285],[12.143,-13.699],[13.747,-9.823],[17,-9.823],[14.415,-15.945],[8.266,-18.5],[2.028,-15.945],[-0.512,-9.823],[-0.512,-6.079]],"c":true}]}],"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[214.286,214.286],"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":"icon","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[8.166,1.704,0],"ix":2,"l":2},"a":{"a":0,"k":[-5.873,13.309,0],"ix":1,"l":2},"s":{"a":0,"k":[101.149,101.149,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],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[8.266,15.285],[-13.747,15.285],[-13.747,-2.863],[8.266,-2.863]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.683,-0.675],[0.98,0],[0.683,0.675],[0,0.94],[-0.683,0.705],[-0.98,0],[-0.683,-0.705],[0,-0.94]],"o":[[-0.683,0.675],[-0.98,0],[-0.683,-0.675],[0,-0.94],[0.683,-0.705],[0.98,0],[0.683,0.705],[0,0.94]],"v":[[-0.245,8.677],[-2.74,9.69],[-5.236,8.677],[-6.261,6.255],[-5.236,3.788],[-2.74,2.731],[-0.245,3.788],[0.78,6.255]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[-0.624,-0.646],[-0.891,0],[0,0],[-0.624,0.617],[0,0.881],[0,0],[0.654,0.617],[0.891,0],[0,0],[0,0],[0,0],[0.654,-0.646],[0,-0.881],[0,0]],"o":[[0.654,0.617],[0,0],[0.891,0],[0.654,-0.646],[0,0],[0,-0.881],[-0.624,-0.646],[0,0],[0,0],[0,0],[-0.891,0],[-0.624,0.617],[0,0],[0,0.881]],"v":[[-16.064,17.575],[-13.747,18.5],[8.266,18.5],[10.539,17.575],[11.519,15.285],[11.519,-2.863],[10.539,-5.11],[8.266,-6.079],[2.74,-6.079],[-0.512,-6.079],[-13.747,-6.079],[-16.064,-5.11],[-17,-2.863],[-17,15.285]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[214.286,214.286],"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":"icon","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"t":170,"s":[43.5,43.5,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"green400","parent":5,"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":[71.264,71.264,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":[0.356862745098,0.725490196078,0.454901960784,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":240,"s":[0]},{"t":270,"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":240,"op":1131,"st":231,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".green400","cl":"green400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.356862745098,0.725490196078,0.454901960784,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":6,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":240,"op":982,"st":82,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.4,0.61568627451,0.964705882353,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":".grey400","cl":"grey400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"t":166,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":".grey600","cl":"grey600","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".grey600","cl":"grey600","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Matte","parent":3,"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,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":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Nail","parent":14,"tt":1,"tp":11,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Matte","parent":3,"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,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":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Finger","parent":3,"tt":1,"tp":13,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".black","cl":"black","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":930,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".black","cl":"black","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_sfps_unlock_to_success.json b/packages/SystemUI/res/raw/biometricprompt_sfps_unlock_to_success.json
new file mode 100644
index 0000000..141ebb7
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_sfps_unlock_to_success.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":240,"op":361,"w":150,"h":150,"nm":"BM_Prompt_FP_to_Unlock","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".blue403","cl":"blue403","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-1.704,8.166,0],"ix":2,"l":2},"a":{"a":0,"k":[-5.873,13.309,0],"ix":1,"l":2},"s":{"a":0,"k":[101.149,101.149,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.4,"y":0},"t":150,"s":[{"i":[[0,0],[0,0],[0.938,1.057],[1.355,0],[0.938,-1.057],[0,-1.527],[0,0],[-1.512,1.674],[-2.111,0],[-1.512,-1.703],[0,-2.408],[0,0]],"o":[[0,0],[0,-1.527],[-0.938,-1.057],[-1.329,0],[-0.938,1.057],[0,0],[0,-2.408],[1.486,-1.703],[2.137,0],[1.486,1.674],[0,0],[0,0]],"v":[[-0.17,-6.078],[-0.17,-9.822],[-1.577,-13.699],[-5.017,-15.284],[-8.419,-13.699],[-9.826,-9.822],[-12.68,-9.822],[-10.412,-15.945],[-5.017,-18.5],[0.456,-15.945],[2.684,-9.822],[2.684,-6.078]],"c":true}]},{"t":165,"s":[{"i":[[0,0],[0,0],[-1.069,1.057],[-1.545,0],[-1.069,-1.057],[0,-1.527],[0,0],[1.723,1.674],[2.406,0],[1.723,-1.703],[0,-2.408],[0,0]],"o":[[0,0],[0,-1.527],[1.069,-1.057],[1.515,0],[1.069,1.057],[0,0],[0,-2.408],[-1.693,-1.703],[-2.436,0],[-1.693,1.674],[0,0],[0,0]],"v":[[2.74,-6.079],[2.74,-9.823],[4.345,-13.699],[8.266,-15.285],[12.143,-13.699],[13.747,-9.823],[17,-9.823],[14.415,-15.945],[8.266,-18.5],[2.028,-15.945],[-0.512,-9.823],[-0.512,-6.079]],"c":true}]}],"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[214.286,214.286],"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":"icon","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".blue402","cl":"blue402","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-1.704,8.166,0],"ix":2,"l":2},"a":{"a":0,"k":[-5.873,13.309,0],"ix":1,"l":2},"s":{"a":0,"k":[101.149,101.149,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],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[8.266,15.285],[-13.747,15.285],[-13.747,-2.863],[8.266,-2.863]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.683,-0.675],[0.98,0],[0.683,0.675],[0,0.94],[-0.683,0.705],[-0.98,0],[-0.683,-0.705],[0,-0.94]],"o":[[-0.683,0.675],[-0.98,0],[-0.683,-0.675],[0,-0.94],[0.683,-0.705],[0.98,0],[0.683,0.705],[0,0.94]],"v":[[-0.245,8.677],[-2.74,9.69],[-5.236,8.677],[-6.261,6.255],[-5.236,3.788],[-2.74,2.731],[-0.245,3.788],[0.78,6.255]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[-0.624,-0.646],[-0.891,0],[0,0],[-0.624,0.617],[0,0.881],[0,0],[0.654,0.617],[0.891,0],[0,0],[0,0],[0,0],[0.654,-0.646],[0,-0.881],[0,0]],"o":[[0.654,0.617],[0,0],[0.891,0],[0.654,-0.646],[0,0],[0,-0.881],[-0.624,-0.646],[0,0],[0,0],[0,0],[-0.891,0],[-0.624,0.617],[0,0],[0,0.881]],"v":[[-16.064,17.575],[-13.747,18.5],[8.266,18.5],[10.539,17.575],[11.519,15.285],[11.519,-2.863],[10.539,-5.11],[8.266,-6.079],[2.74,-6.079],[-0.512,-6.079],[-13.747,-6.079],[-16.064,-5.11],[-17,-2.863],[-17,15.285]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[214.286,214.286],"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":"icon","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":3,"nm":"Null 29","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":150,"s":[64,64,100]},{"t":170,"s":[43.5,43.5,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"green400","parent":5,"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":[71.264,71.264,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":[0.356862745098,0.725490196078,0.454901960784,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":240,"s":[0]},{"t":270,"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":240,"op":1131,"st":231,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".green400","cl":"green400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[0]},{"t":248,"s":[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,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.356862745098,0.725490196078,0.454901960784,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":6,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":240,"op":982,"st":82,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":240,"s":[100]},{"t":248,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.4,0.61568627451,0.964705882353,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":".grey400","cl":"grey400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[100]},{"t":166,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":150,"s":[4]},{"t":170,"s":[6]}],"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":".grey600","cl":"grey600","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.422,1.727,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,-2.148],[0,0],[2.171,0.019],[0,0]],"o":[[0,0],[0,2.148],[0,0],[2.171,0.084]],"v":[[1.504,-10.64],[1.504,10.641],[-2.285,14.585],[-2.285,-14.582]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".grey600","cl":"grey600","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.73,0.002,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":[[-1.503,-0.24],[0,0],[1.545,-0.103],[0,0]],"o":[[0,0],[-1.503,0.24],[0,0],[1.545,0.103]],"v":[[2.287,-49.365],[2.287,49.365],[-2.287,49.875],[-2.287,-49.875]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Matte","parent":3,"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,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":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Nail","parent":14,"tt":1,"tp":11,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.413,-32.45,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":[[-2.537,-10.49],[3.914,3.121],[0.029,0.49],[-0.203,0.012]],"o":[[0,0],[-5.309,-4.235],[0.195,-0.025],[6.139,-0.367]],"v":[[5.837,9.643],[-1.02,8.379],[-5.837,-9.817],[-5.232,-9.874]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Matte","parent":3,"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,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":[[-27.614,0],[0,27.614],[27.614,0],[0,-27.614]],"o":[[27.614,0],[0,-27.614],[-27.614,0],[0,27.614]],"v":[[0,50],[50,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Finger","parent":3,"tt":1,"tp":13,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[43]},{"t":105,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[53.57,92.052,0],"to":[-14.604,-5.758,0],"ti":[0.932,11.227,0]},{"t":105,"s":[29.227,68.052,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.948,45.138,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":[[-4.392,-3.688],[0,0],[-1.205,-3.8],[-1.473,-3.596],[9.145,-3.485],[1.549,12.262],[-8.315,0.872]],"o":[[3.368,2.829],[0.954,3.951],[1.895,5.97],[-5.664,7.791],[-3.418,-14.412],[-2.036,-16.119],[0.029,0.49]],"v":[[-0.286,-13.646],[6.116,-11.991],[9.253,-0.135],[15.167,17.416],[-8.324,31.452],[-14.517,-6.098],[-5.559,-31.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".black","cl":"black","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.782,1.408,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":[[-1.716,3.431],[1.716,0],[-1.716,-3.431]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.268,1.408,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,8.054],[-8.054,0]],"o":[[-8.054,0],[0,-8.054],[0,0]],"v":[[7.292,14.583],[-7.292,0],[7.292,-14.583]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".blue401","cl":"blue401","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[50]},{"t":130,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":30,"s":[0,0,100]},{"t":120,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":930,"st":30,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":30,"s":[50]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.33,1.408,0],"ix":2,"l":2},"a":{"a":0,"k":[22.5,-0.242,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.667],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":90,"s":[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,16.658],[-16.658,0]],"o":[[-16.658,0],[0,-16.658],[0,0]],"v":[[15.081,30.161],[-15.081,0],[15.081,-30.161]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,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":[150,150],"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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".black","cl":"black","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"t":158,"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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-31.25,-2.604],[0,27.614],[0,0],[0,-27.614]],"o":[[0,-0.13],[0,-27.614],[-27.344,-0.651],[0,27.614]],"v":[[0,50],[1.172,0],[0,-50],[-50,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[150,150],"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":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":0,"op":900,"st":0,"ct":1,"bm":0}],"markers":[]}
\ 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
deleted file mode 100644
index 034ac87..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_fingerprint_landscape.json
+++ /dev/null
@@ -1 +0,0 @@
-{"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
deleted file mode 100644
index e5cc565e..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_fingerprint_portrait_bottomright.json
+++ /dev/null
@@ -1 +0,0 @@
-{"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
deleted file mode 100644
index b082265..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_fingerprint_portrait_topleft.json
+++ /dev/null
@@ -1 +0,0 @@
-{"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
deleted file mode 100644
index befe3bb..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_success_landscape.json
+++ /dev/null
@@ -1 +0,0 @@
-{"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
deleted file mode 100644
index d75b335..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_success_portrait_bottomright.json
+++ /dev/null
@@ -1 +0,0 @@
-{"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
deleted file mode 100644
index e6b2db1..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_success_portrait_topleft.json
+++ /dev/null
@@ -1 +0,0 @@
-{"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
deleted file mode 100644
index 0da143c..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_symbol_fingerprint_to_error_portrait_bottomright.json
+++ /dev/null
@@ -1 +0,0 @@
-{"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
deleted file mode 100644
index 15457c7..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_symbol_fingerprint_to_error_portrait_topleft.json
+++ /dev/null
@@ -1 +0,0 @@
-{"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
deleted file mode 100644
index f39894b..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_symbol_fingerprint_to_success_landscape.json
+++ /dev/null
@@ -1 +0,0 @@
-{"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
deleted file mode 100644
index 6d4f4e2..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_symbol_fingerprint_to_success_portrait_bottomright.json
+++ /dev/null
@@ -1 +0,0 @@
-{"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
deleted file mode 100644
index b7bb0d5..0000000
--- a/packages/SystemUI/res/raw/biometricprompt_symbol_fingerprint_to_success_portrait_topleft.json
+++ /dev/null
@@ -1 +0,0 @@
-{"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 d5ca85c..8c685ff 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Werkverrigting"</string>
<string name="user_interface" msgid="3712869377953950887">"Gebruikerkoppelvlak"</string>
<string name="thermal" msgid="6758074791325414831">"Termies"</string>
+ <string name="custom" msgid="3337456985275158299">"Gepasmaak"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Gepasmaakte Nasporinginstellings"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Stel verstek terug"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Eenhandmodus"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Gehoortoestelle"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktief"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioriteitmodusse"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Klaar"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Instellings"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Aan"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Af"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Jy sal nie deur geluide en vibrasies gepla word nie, behalwe deur wekkers, herinneringe, geleenthede en bellers wat jy spesifiseer. Jy sal steeds enigiets hoor wat jy kies om te speel, insluitend musiek, video\'s en speletjies."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Jy sal nie deur geluide en vibrasies gepla word nie, behalwe deur wekkers. Jy sal steeds enigiets hoor wat jy kies om te speel, insluitend musiek, video\'s en speletjies."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans stadig • Vol oor <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> • Laai tans • Vol oor <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Legstukke op sluitskerm"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swiep links om die gemeenskaplike tutoriaal te begin"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Pasmaak"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Maak toe"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"plaas gekose legstuk"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Sluitskermlegstukke"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Enigiemand kan legstukke op jou sluitskerm sien, selfs al is jou tablet gesluit."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ontkies legstuk"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Sluitskermlegstukke"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Om ’n app met ’n legstuk oop te maak, sal jy moet verifieer dat dit jy is. Hou ook in gedagte dat enigeen dit kan bekyk, selfs wanneer jou tablet gesluit is. Sommige legstukke is moontlik nie vir jou sluitskerm bedoel nie en dit kan onveilig wees om dit hier by te voeg."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Het dit"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Begin nou"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Geen kennisgewings nie"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Geen nuwe kennisgewings nie"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Kennisgewingdemping is aan"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Jou toestelvolume en -waarskuwings word outomaties vir tot 2 minute lank verminder wanneer jy te veel kennisgewings op een slag kry."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Skakel af"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Ontsluit om ouer kennisgewings te sien"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Hierdie toestel word deur jou ouer bestuur"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Stawing word vereis. Raak die vingerafdruksensor om te staaf."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Oproep aan die gang"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiele data"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Gekoppel"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tydelik gekoppel"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Swak verbinding"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Klaar"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Uitstekende werk!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Gaan terug"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Swiep enige plek op die raakpaneel links of regs met drie vingers om terug te gaan."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Raakpaneel wat drie vingers wat regs en links beweeg wys"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Toestelskerm wat animasie vir teruggebaar wys"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Sleutelbordlig"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Huiskontroles"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Kry vinnig toegang tot jou huiskontroles as ’n sluimerskerm"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Ontdoen"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Swiep links of regs met drie vingers op die raakpaneel om terug te gaan"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Swiep op met drie vingers op die raakpaneel om terug na die tuisskerm te gaan"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Swiep op en hou met drie vingers op die raakpaneel om onlangse apps te bekyk"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Druk die handelingsleutel op jou sleutelbord om al jou apps te bekyk"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Gebruik jou raakpaneel om terug te gaan"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Swiep links of regs met drie vingers. Tik om meer gebare te leer."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Gebruik jou raakpaneel om na die tuisskerm toe te gaan"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Swiep op met drie vingers. Tik om meer gebare te leer."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Gebruik jou raakpaneel om onlangse apps te bekyk"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swiep op en hou met drie vingers. Tik om meer gebare te leer."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Gebruik jou sleutelbord om alle apps te bekyk"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Druk enige tyd die handelingsleutel. Tik om meer gebare te leer."</string>
</resources>
diff --git a/packages/SystemUI/res/values-af/tiles_states_strings.xml b/packages/SystemUI/res/values-af/tiles_states_strings.xml
index d30156f..1b4781d 100644
--- a/packages/SystemUI/res/values-af/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-af/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Af"</item>
<item msgid="4875147066469902392">"Aan"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Onbeskikbaar"</item>
- <item msgid="2004750556637773692">"Af"</item>
- <item msgid="8968530753931637871">"Aan"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Onbeskikbaar"</item>
<item msgid="5044688398303285224">"Af"</item>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index f3edff7..26e5c1e5 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"አፈጻጸም"</string>
<string name="user_interface" msgid="3712869377953950887">"የተጠቃሚ በይነገፅ"</string>
<string name="thermal" msgid="6758074791325414831">"ተርማል"</string>
+ <string name="custom" msgid="3337456985275158299">"ብጁ"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"የብጁ መከታተያ ቅንብሮች"</string>
+ <string name="restore_default" msgid="5259420807486239755">"ወደ ነባሪ መልስ"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"የአንድ እጅ ሁነታ"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"የመስሚያ መሣሪያዎች"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"ገቢር"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"ቅድሚያ ሁነታዎች"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"ተከናውኗል"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ቅንብሮች"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"በርቷል"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"ጠፍቷል"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"እርስዎ ከወሰንዋቸው ማንቂያዎች፣ አስታዋሾች፣ ክስተቶች እና ደዋዮች በስተቀር፣ በድምጾች እና ንዝረቶች አይረበሹም። ሙዚቃ፣ ቪዲዮዎች እና ጨዋታዎች ጨምሮ ለመጫወት የሚመርጡትን ማንኛውም ነገር አሁንም ይሰማሉ።"</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"ከማንቂያዎች በስተቀር፣ በድምጾች እና ንዝረቶች አይረበሹም። ሙዚቃ፣ ቪዲዮዎች እና ጨዋታዎች ጨምሮ ለመጫወት የሚመርጡትን ማንኛውም ነገር አሁንም ይሰማሉ።"</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • በዝግታ ኃይልን በመሙላት ላይ • በ<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> • ኃይል በመሙላት ላይ • በ<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ውስጥ ይሞላል"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ምግብሮች በማያ ገጽ ቁልፍ ላይ"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"የጋራ አጋዥ ሥልጠናውን ለመጀመር ወደ ግራ ያንሸራትቱ።"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"አብጅ"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"አሰናብት"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"በቦታ የተመረጠ ምግብር"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"የማያ ገፅ ቁልፍ ምግብሮች"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"የእርስዎ ጡባዊ ቁልፍ ተቆልፎ ቢሆን እንኳን ማንኛውም ሰው በማያ ገፅ ቁልፍዎ ላይ ምግብሮችን ማየት ይችላል።"</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ምግብር አትምረጥ"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"የማያ ገፅ ቁልፍ ምግብሮች"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ምግብር በመጠቀም መተግበሪያ ለመክፈት እርስዎ መሆንዎን ማረጋገጥ አለብዎት። እንዲሁም የእርስዎ ጡባዊ በተቆለፈበት ጊዜ እንኳን ማንኛውም ሰው እነሱን ማየት እንደሚችል ከግምት ውስጥ ያስገቡ። አንዳንድ ምግብሮች ለማያ ገፅ ቁልፍዎ የታሰቡ ላይሆኑ ይችላሉ እና እዚህ ለማከል አስተማማኝ ላይሆኑ ይችላሉ።"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"ገባኝ"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"አሁን ጀምር"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"ምንም ማሳወቂያ የለም"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"ምንም አዲስ ማሳወቂያዎች የሉም"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"የማሳወቂያ ረጋ ማለት በርቷል"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"በአንድ ጊዜ ብዙ ማሳወቂያዎችን ሲያገኙ የመሣሪያዎ ድምፅ እና ማንቂያዎች እስከ 2 ደቂቃዎች ድረስ በራስ-ሰር ይቀንሳሉ።"</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"አጥፋ"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"የቆዩ ማሳወቂያዎችን ለማየት ይክፈቱ"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ይህ መሣሪያ በእርስዎ ወላጅ የሚተዳደር ነው።"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ማረጋገጥ ያስፈልጋል። ለማረጋገጥ የጣት አሻራ ዳሳሹን ይንኩ።"</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"በመካሄድ ላይ የስልክ ጥሪ"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"የተንቀሳቃሽ ስልክ ውሂብ"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"ተገናኝቷል"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"በጊዜያዊነት ተገናኝቷል"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"ደካማ ግንኙነት"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ተከናውኗል"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ጥሩ ሠርተዋል!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ወደኋላ ተመለስ"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"ወደኋላ ለመመለስ በመዳሰሻ ሰሌዳው ላይ በየትኛውም ቦታ ሦስት ጣቶችን በመጠቀም ወደግራ ወይም ወደቀኝ ያንሸራትቱ።"</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ሦስት ጣቶች ወደቀኝ እና ግራ ሲንቀሳቀሱ የሚያሳይ የመዳሰሻ ሰሌዳ"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"የኋላ ምልክት እነማ የሚያሳይ የመሣሪያ ማያ ገፅ"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"የቁልፍ ሰሌዳ የጀርባ ብርሃን"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"የቤት ውስጥ ቁጥጥሮች"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"የቤት መቆጣጠሪያዎችዎን እንደ የገጸ ማያ አሳራፊ በፍጥነት ይድረሱባቸው"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"ቀልብስ"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"ለመመለስ የመዳሰሻ ሰሌዳው ላይ በሦስት ጣቶች ወደግራ ወይም ወደቀኝ ያንሸራትቱ"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"ወደ መነሻ ለመሄድ የመዳሰሻ ሰሌዳው ላይ በሦስት ጣቶች ወደላይ ያንሸራትቱ"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"የቅርብ ጊዜ መተግበሪያዎችን ለማየት የመዳሰሻ ሰሌዳው ላይ በሦስት ጣቶች ወደላይ ያንሸራትቱ እና ይያዙ"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ሁሉንም መተግበሪያዎችዎን ለማየት በቁልፍ ሰሌዳዎ ላይ ያለውን የተግባር ቁልፍ ይጫኑ"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"ለመመለስ የመዳሰሻ ሰሌዳዎን ይጠቀሙ"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"ሦስት ጣቶችን በመጠቀም ወደ ግራ ወይም ወደ ቀኝ ያንሸራትቱ። ምልክቶችን የበለጠ ለማወቅ መታ ያድርጉ።"</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"ወደ መነሻ ለመመለስ የመዳሰሻ ሰሌዳዎን ይጠቀሙ"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"ሦስት ጣቶችን በመጠቀም ወደላይ ያንሸራትቱ። ምልክቶችን የበለጠ ለማወቅ መታ ያድርጉ።"</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"የቅርብ ጊዜ መተግበሪያዎችን ለማየት የመዳሰሻ ሰሌዳዎን ይጠቀሙ"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"ሦስት ጣቶችን በመጠቀም ወደላይ ያንሸራትቱ እና ይያዙ። ምልክቶችን የበለጠ ለማወቅ መታ ያድርጉ።"</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"ሁሉንም መተግበሪያዎች ለማየት የቁልፍ ሰሌዳዎን ይጠቀሙ"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"በማንኛውም ጊዜ የተግባር ቁልፍን ይጫኑ። ምልክቶችን የበለጠ ለማወቅ መታ ያድርጉ።"</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/tiles_states_strings.xml b/packages/SystemUI/res/values-am/tiles_states_strings.xml
index 40cb02e..a3c590c 100644
--- a/packages/SystemUI/res/values-am/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-am/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"ጠፍቷል"</item>
<item msgid="4875147066469902392">"በርቷል"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"አይገኝም"</item>
- <item msgid="2004750556637773692">"ጠፍቷል"</item>
- <item msgid="8968530753931637871">"በርቷል"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"አይገኝም"</item>
<item msgid="5044688398303285224">"ጠፍቷል"</item>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index d5243f5..3b65cd8 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -210,9 +210,9 @@
<string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"عند إدخال نقش غير صحيح في المحاولة التالية، سيتم حذف هذا المستخدم."</string>
<string name="biometric_dialog_last_pin_attempt_before_wipe_user" msgid="4159878829962411168">"عند إدخال رقم تعريف شخصي غير صحيح في المحاولة التالية، سيتم حذف هذا المستخدم."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_user" msgid="4695682515465063885">"عند إدخال كلمة مرور غير صحيحة في المحاولة التالية، سيتم حذف هذا المستخدم."</string>
- <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"عند إدخال نقش غير صحيح في المحاولة التالية، سيتم حذف ملفك الشخصي للعمل وبياناته."</string>
- <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"عند إدخال رقم تعريف شخصي غير صحيح في المحاولة التالية، سيتم حذف ملفك الشخصي للعمل وبياناته."</string>
- <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"عند إدخال كلمة مرور غير صحيحة في المحاولة التالية، سيتم حذف ملفك الشخصي للعمل وبياناته."</string>
+ <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"عند إدخال نقش غير صحيح في المحاولة التالية، سيتم حذف ملف العمل الخاص بك وبياناته."</string>
+ <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"عند إدخال رقم تعريف شخصي غير صحيح في المحاولة التالية، سيتم حذف ملف العمل الخاص بك وبياناته."</string>
+ <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"عند إدخال كلمة مرور غير صحيحة في المحاولة التالية، سيتم حذف ملف العمل الخاص بك وبياناته."</string>
<string name="biometric_re_enroll_dialog_confirm" msgid="3049858021857801836">"إعداد"</string>
<string name="biometric_re_enroll_dialog_cancel" msgid="93760939407091417">"لاحقًا"</string>
<string name="biometric_re_enroll_notification_content" msgid="8685925877186288180">"هذا الإجراء مطلوب لتحسين مستوى الأمان والأداء."</string>
@@ -222,11 +222,11 @@
<string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"لإعادة إعداد ميزة \"فتح الجهاز ببصمة الإصبع\"، سيتم حذف صور بصمة الإصبع ونماذجها.\n\nبعد حذفها، عليك إعادة إعداد ميزة \"فتح الجهاز ببصمة الإصبع\" لتتمكن من استخدام بصمة الإصبع في فتح قفل الهاتف أو إثبات هويتك."</string>
<string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"لإعادة إعداد ميزة \"فتح الجهاز ببصمة الإصبع\"، سيتم حذف صور بصمة الإصبع ونموذجها.\n\nبعد حذفها، عليك إعادة إعداد ميزة \"فتح الجهاز ببصمة الإصبع\" لتتمكن من استخدام بصمة الإصبع في فتح قفل الهاتف أو إثبات هويتك."</string>
<string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"تعذّر إعداد ميزة \"فتح الجهاز ببصمة الإصبع\". انتقِل إلى \"الإعدادات\" لإعادة المحاولة."</string>
- <string name="face_re_enroll_notification_title" msgid="1850838867718410520">"إعادة إعداد ميزة \"فتح الجهاز بالتعرّف على الوجه\""</string>
- <string name="face_re_enroll_notification_name" msgid="7384545252206120659">"فتح الجهاز بالتعرّف على الوجه"</string>
- <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"إعداد ميزة \"فتح الجهاز بالتعرّف على الوجه\""</string>
- <string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"لإعادة إعداد ميزة \"فتح الجهاز بالتعرّف على الوجه\"، سيتم حذف نموذج الوجه الحالي.\n\nعليك إعادة إعداد الميزة لتتمكن من فتح قفل الهاتف باستخدام وجهك."</string>
- <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"تعذّر إعداد ميزة \"فتح الجهاز بالتعرّف على الوجه\". انتقِل إلى \"الإعدادات\" لإعادة المحاولة."</string>
+ <string name="face_re_enroll_notification_title" msgid="1850838867718410520">"إعادة إعداد ميزة \"فتح الجهاز ببصمة الوجه\""</string>
+ <string name="face_re_enroll_notification_name" msgid="7384545252206120659">"فتح الجهاز ببصمة الوجه"</string>
+ <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"إعداد ميزة \"فتح الجهاز ببصمة الوجه\""</string>
+ <string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"لإعادة إعداد ميزة \"فتح الجهاز ببصمة الوجه\"، سيتم حذف نموذج الوجه الحالي.\n\nعليك إعادة إعداد الميزة لتتمكن من فتح قفل الهاتف باستخدام وجهك."</string>
+ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"تعذّر إعداد ميزة \"فتح الجهاز ببصمة الوجه\". انتقِل إلى \"الإعدادات\" لإعادة المحاولة."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"المس أداة استشعار بصمة الإصبع"</string>
<string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"للمتابعة، اضغط على رمز فتح القفل."</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"يتعذّر التعرّف على الوجه. يمكنك استخدام بصمة إصبعك."</string>
@@ -234,7 +234,7 @@
<skip />
<string name="keyguard_face_failed" msgid="2346762871330729634">"يتعذّر التعرّف على الوجه."</string>
<string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"يمكنك استخدام بصمة إصبعك."</string>
- <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"ميزة \"فتح الجهاز بالتعرف على الوجه\" غير متاحة."</string>
+ <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"ميزة \"فتح الجهاز ببصمة الوجه\" غير متاحة."</string>
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"تم توصيل البلوتوث."</string>
<string name="accessibility_bluetooth_device_icon" msgid="9163840051642587982">"رمز الجهاز الذي يتضمّن بلوتوث"</string>
<string name="accessibility_bluetooth_device_settings_gear" msgid="3314916468105272540">"انقر هنا لضبط إعدادات الجهاز."</string>
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"الأداء"</string>
<string name="user_interface" msgid="3712869377953950887">"واجهة المستخدم"</string>
<string name="thermal" msgid="6758074791325414831">"الأداء الحراري"</string>
+ <string name="custom" msgid="3337456985275158299">"مخصّص"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"إعدادات التتبع المخصصة"</string>
+ <string name="restore_default" msgid="5259420807486239755">"استعادة الإعدادات التلقائية"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"وضع \"التصفح بيد واحدة\""</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"سماعات الأذن الطبية"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"متّصلة حاليًا"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"الأوضاع ذات الأولوية"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"تم"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"الإعدادات"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"مفعَّل"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"غير مفعَّل"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"لن يتم إزعاجك بالأصوات والاهتزاز، باستثناء المُنبِّهات والتذكيرات والأحداث والمتصلين الذين تحددهم. وسيظل بإمكانك سماع أي عناصر أخرى تختار تشغيلها، بما في ذلك الموسيقى والفيديوهات والألعاب."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"لن يتم إزعاجك بالأصوات والاهتزاز، باستثناء المُنبِّهات. وسيظل بإمكانك سماع أي عناصر أخرى تختار تشغيلها، بما في ذلك الموسيقى والفيديوهات والألعاب."</string>
@@ -443,14 +450,14 @@
<string name="keyguard_unlock" msgid="8031975796351361601">"التمرير إلى الأعلى لفتح القفل"</string>
<string name="keyguard_unlock_press" msgid="9140109453735019209">"اضغط على رمز فتح القفل لفتح قفل الشاشة."</string>
<string name="keyguard_face_successful_unlock_swipe" msgid="6180997591385846073">"تم فتح قفل جهازك عند تقريبه من وجهك. مرِّر سريعًا للأعلى لفتح الجهاز."</string>
- <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"تم فتح القفل بالتعرّف على وجهك. لفتح الجهاز، اضغط على رمز فتح القفل."</string>
+ <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"تم فتح القفل ببصمة وجهك. لفتح الجهاز، اضغط على رمز فتح القفل."</string>
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"تم فتح قفل جهازك عند تقريبه من وجهك. اضغط لفتح الجهاز."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"تم التعرّف على الوجه. اضغط لفتح الجهاز."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"تم التعرّف على الوجه. اضغط على رمز فتح القفل لفتح الجهاز."</string>
<string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"تم فتح قفل جهازك عند تقريبه من وجهك."</string>
<string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"تم التعرّف على الوجه."</string>
<string name="keyguard_retry" msgid="886802522584053523">"مرِّر سريعًا للأعلى لإعادة المحاولة."</string>
- <string name="accesssibility_keyguard_retry" msgid="8880238862712870676">"مرِّر سريعًا للأعلى لاستخدام \"فتح الجهاز بالتعرف على الوجه\""</string>
+ <string name="accesssibility_keyguard_retry" msgid="8880238862712870676">"مرِّر سريعًا للأعلى لاستخدام ميزة \"فتح الجهاز ببصمة الوجه\""</string>
<string name="require_unlock_for_nfc" msgid="1305686454823018831">"افتح قفل الشاشة لاستخدام تقنية NFC"</string>
<string name="do_disclosure_generic" msgid="4896482821974707167">"هذا الجهاز يخص مؤسستك."</string>
<string name="do_disclosure_with_name" msgid="2091641464065004091">"هذا الجهاز يخص <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن ببطء • ستمتلئ البطارية خلال <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> • جارٍ الشحن • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"التطبيقات المصغّرة على شاشة القفل"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"مرِّر سريعًا لليمين لبدء الدليل التوجيهي العام."</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"تخصيص"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"إغلاق"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"إضافة التطبيق المصغّر المحدَّد"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"التطبيقات المصغّرة المصمَّمة لشاشة القفل"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"يمكن للجميع رؤية التطبيقات المصغّرة على شاشة القفل، حتى في حال قفل الجهاز اللوحي."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"إلغاء اختيار التطبيق المصغّر"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"التطبيقات المصغّرة المصمَّمة لشاشة القفل"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"لفتح تطبيق باستخدام تطبيق مصغَّر، عليك إثبات هويتك. يُرجى ملاحظة أنّ أي شخص يمكنه الاطّلاع محتوى التطبيقات المصغَّرة، حتى وإن كان جهازك اللوحي مُقفلاً. بعض التطبيقات المصغّرة قد لا تكون مُصمَّمة لإضافتها إلى شاشة القفل، وقد يكون هذا الإجراء غير آمن."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"حسنًا"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"البدء الآن"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"ما مِن إشعارات"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"ما مِن إشعارات جديدة"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"ميزة \"تخفيض الإشعارات الصوتية والاهتزاز\" مُفعَّلة"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"يتم تلقائيًا خفض مستوى صوت جهازك والتنبيهات لمدة تصل إلى دقيقتين عند تلقّي إشعارات كثيرة في آنٍ واحد."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"إيقاف"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"افتَح قفل الشاشة لعرض الإشعارات الأقدم."</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"يتولّى أحد الوالدين إدارة هذا الجهاز."</string>
@@ -574,7 +580,7 @@
<string name="quick_settings_disclosure_management_vpns" msgid="929181757984262902">"ينتمي هذا الجهاز إلى مؤسستك، ويتّصل بالإنترنت من خلال خدمات الشبكة الافتراضية الخاصة (VPN)."</string>
<string name="quick_settings_disclosure_named_management_vpns" msgid="3312645578322079185">"ينتمي هذا الجهاز إلى <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>، ويتّصل بالإنترنت من خلال خدمات الشبكة الافتراضية الخاصة (VPN)."</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"يمكن لمؤسستك مراقبة حركة بيانات الشبكة في ملف العمل"</string>
- <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"يمكن لـ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> مراقبة حركة بيانات الشبكة في ملفك الشخصي للعمل"</string>
+ <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"يمكن لـ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> مراقبة حركة بيانات الشبكة في ملف العمل الخاص بك"</string>
<string name="quick_settings_disclosure_managed_profile_network_activity" msgid="2636594621387832827">"تكون أنشطة شبكة ملف العمل مرئية لمشرف تكنولوجيا المعلومات."</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"قد تكون الشبكة خاضعة للمراقبة"</string>
<string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"هذا الجهاز متّصل بالإنترنت من خلال خدمات الشبكات الافتراضية الخاصة (VPN)."</string>
@@ -592,10 +598,10 @@
<string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"قد تتمكّن مؤسسة <xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> من الوصول إلى البيانات المرتبطة بهذا الجهاز وإدارة التطبيقات وتغيير إعدادات الجهاز.\n\nإذا كان لديك أسئلة، يُرجى التواصل مع <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"هذا الجهاز يخص مؤسستك.\n\nيمكن لمشرف تكنولوجيا المعلومات في مؤسستك تتبّع وإدارة الإعدادات والتطبيقات والبيانات المرتبطة بجهازك ومعلومات الموقع الجغرافي للجهاز وعمليات الدخول إلى نظام المؤسسة.\n\nللحصول على المزيد من المعلومات، يمكنك التواصل مع مشرف تكنولوجيا المعلومات."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"ثبّتت مؤسستك مرجعًا مصدّقًا على هذا الجهاز. قد تتم مراقبة حركة بيانات شبكتك الآمنة أو تعديلها."</string>
- <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"ثبّتت مؤسستك مرجعًا مصدّقًا في ملفك الشخصي للعمل. قد تتم مراقبة حركة بيانات شبكتك الآمنة أو تعديلها."</string>
+ <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"ثبّتت مؤسستك مرجعًا مصدّقًا في ملف العمل الخاص بك. قد تتم مراقبة حركة بيانات شبكتك الآمنة أو تعديلها."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"تم تثبيت مرجع مصدّق على هذا الجهاز. قد تتم مراقبة حركة بيانات شبكتك الآمنة أو تعديلها."</string>
<string name="monitoring_description_management_network_logging" msgid="216983105036994771">"شغَّل المشرف ميزة تسجيل بيانات الشبكة، والتي يتم من خلالها مراقبة حركة البيانات على جهازك."</string>
- <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"شغَّل المشرف ميزة تسجيل بيانات الشبكة، والتي يتم من خلالها مراقبة حركة البيانات في ملفك الشخصي للعمل ولكن لا تتم مراقبتها في ملفك الشخصي."</string>
+ <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"شغَّل المشرف ميزة تسجيل بيانات الشبكة، والتي يتم من خلالها مراقبة حركة البيانات في ملف العمل الخاص بك ولكن لا تتم مراقبتها في ملفك الشخصي."</string>
<string name="monitoring_description_named_vpn" msgid="8220190039787149671">"هذا الجهاز متّصل بالإنترنت من خلال \"<xliff:g id="VPN_APP">%1$s</xliff:g>\". ويمكن لمقدِّم شبكة VPN الاطّلاع على أنشطة الشبكة، بما في ذلك الرسائل الإلكترونية وبيانات التصفّح."</string>
<string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"هذا الجهاز متّصل بالإنترنت من خلال \"<xliff:g id="VPN_APP">%1$s</xliff:g>\". تجدر الإشارة إلى أنّ أنشطة الشبكة، بما في ذلك الرسائل الإلكترونية وبيانات التصفُّح، مرئية لمشرف تكنولوجيا المعلومات في مؤسستك."</string>
<string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"هذا الجهاز متّصل بالإنترنت من خلال <xliff:g id="VPN_APP_0">%1$s</xliff:g> و<xliff:g id="VPN_APP_1">%2$s</xliff:g>. يمكن لمشرف تكنولوجيا المعلومات رؤية أنشطة الشبكة، بما في ذلك الرسائل الإلكترونية وبيانات التصفُّح."</string>
@@ -687,7 +693,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"عرض الوضع التجريبي"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"إيثرنت"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"المنبّه"</string>
- <string name="wallet_title" msgid="5369767670735827105">"محفظة"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"محفظة Google"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"يمكنك إعداد طريقة دفع لإجراء عمليات شراء بسرعة وأمان أكبر باستخدام هاتفك."</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"عرض الكل"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"انقر لفتح قفل الجهاز"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"المصادقة مطلوبة. المس مستشعر بصمات الإصبع للمصادقة."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"مكالمة هاتفية جارية"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"بيانات الجوّال"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"متصلة بالإنترنت"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"متصلة مؤقتًا"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"الاتصال ضعيف"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"تم"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"أحسنت."</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"رجوع"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"للرجوع، مرِّر سريعًا لليسار أو لليمين باستخدام ثلاثة أصابع في أي مكان على لوحة اللمس."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"لوحة لمس تعرض ثلاثة أصابع تتحرك يمينًا ويسارًا"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"شاشة جهاز تعرض صورة متحركة لإيماءة الرجوع"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"الإضاءة الخلفية للوحة المفاتيح"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"إدارة المنزل آليًّا"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"يمكنك إدارة المنزل آليًّا بشكل سريع من شاشة الاستراحة"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"تراجع"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"للرجوع، مرِّر سريعًا لليمين أو لليسار على لوحة اللمس باستخدام 3 أصابع"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"للانتقال إلى الشاشة الرئيسية، مرِّر سريعًا للأعلى على لوحة اللمس باستخدام 3 أصابع"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"لعرض التطبيقات المستخدَمة مؤخرًا، مرِّر سريعًا للأعلى مع استمرار الضغط على لوحة اللمس باستخدام 3 أصابع"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"لعرض جميع التطبيقات، اضغط على مفتاح الإجراء في لوحة المفاتيح"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"استخدِم لوحة اللمس للرجوع"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"مرِّر سريعًا لليمين أو لليسار باستخدام 3 أصابع. انقر للتعرّف على المزيد من الإيماءات."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"استخدِم لوحة اللمس للانتقال إلى الشاشة الرئيسية"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"مرِّر سريعًا للأعلى باستخدام 3 أصابع. انقر للتعرّف على المزيد من الإيماءات."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"استخدِم لوحة اللمس لعرض التطبيقات المستخدَمة مؤخرًا"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"مرِّر سريعًا للأعلى مع استمرار الضغط باستخدام 3 أصابع. انقر للتعرّف على المزيد من الإيماءات."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"استخدِم لوحة المفاتيح لعرض جميع التطبيقات"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"اضغط على مفتاح الإجراء في أي وقت. انقر للتعرّف على المزيد من الإيماءات."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/tiles_states_strings.xml b/packages/SystemUI/res/values-ar/tiles_states_strings.xml
index acb38fe..a89650a 100644
--- a/packages/SystemUI/res/values-ar/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ar/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"الميزة غير مفعّلة"</item>
<item msgid="4875147066469902392">"الميزة مفعّلة"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"غير متوفّرة"</item>
- <item msgid="2004750556637773692">"غير مفعَّلة"</item>
- <item msgid="8968530753931637871">"مفعَّلة"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"الميزة غير متاحة"</item>
<item msgid="5044688398303285224">"الميزة غير مفعّلة"</item>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index b1fa417..576e8ad 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"পাৰদৰ্শিতা"</string>
<string name="user_interface" msgid="3712869377953950887">"ব্যৱহাৰকাৰীৰ ইণ্টাৰফে’চ"</string>
<string name="thermal" msgid="6758074791325414831">"থাৰ্মেল"</string>
+ <string name="custom" msgid="3337456985275158299">"কাষ্টম"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"কাষ্টম ট্ৰে’চৰ ছেটিং"</string>
+ <string name="restore_default" msgid="5259420807486239755">"ডিফ’ল্ট পুনঃস্থাপন কৰক"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"এখন হাতেৰে ব্যৱহাৰ কৰা ম’ড"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"শুনাৰ ডিভাইচ"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"সক্ৰিয় হৈ আছে"</string>
@@ -429,10 +432,11 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"অগ্ৰাধিকাৰপ্ৰাপ্ত ম’ডসমূহ"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"কৰা হ’ল"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ছেটিং"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
- <skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
- <skip />
+ <string name="zen_mode_on" msgid="9085304934016242591">"অন আছে"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"অফ আছে"</string>
+ <string name="zen_mode_set_up" msgid="7457957033034460064">"ছেট আপ কৰক"</string>
+ <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"ছেটিঙত পৰিচালনা কৰক"</string>
+ <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{কোনো সক্ৰিয় ম’ড নাই}=1{{mode} সক্ৰিয় আছে}one{# টা ম’ড সক্ৰিয় আছে}other{# টা ম’ড সক্ৰিয় আছে}}"</string>
<string name="zen_priority_introduction" msgid="3159291973383796646">"আপুনি নিৰ্দিষ্ট কৰা এলাৰ্ম, ৰিমাইণ্ডাৰ, ইভেন্ট আৰু কল কৰোঁতাৰ বাহিৰে আন কোনো শব্দৰ পৰা আপুনি অসুবিধা নাপাব। কিন্তু, সংগীত, ভিডিঅ\' আৰু খেলসমূহকে ধৰি আপুনি প্লে কৰিব খোজা যিকোনো বস্তু তথাপি শুনিব পাৰিব।"</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"আপুনি নিৰ্দিষ্ট কৰা এলাৰ্মৰ বাহিৰে আন কোনো ধ্বনি আৰু কম্পনৰ পৰা আপুনি অসুবিধা নাপাব। কিন্তু, সংগীত, ভিডিঅ\' আৰু খেলসমূহকে ধৰি আপুনি প্লে কৰিব খোজা যিকোনো বস্তু তথাপি শুনিব পাৰিব।"</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"কাষ্টমাইজ কৰক"</string>
@@ -471,6 +475,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • লাহে লাহে চাৰ্জ হৈ আছে • <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> • চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"লক স্ক্ৰীনত ৱিজেট"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"সম্প্ৰদায় সম্পৰ্কীয় নিৰ্দেশনা আৰম্ভ কৰিবলৈ বাওঁফালে ছোৱাইপ কৰক"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"কাষ্টমাইজ কৰক"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"অগ্ৰাহ্য কৰক"</string>
@@ -499,8 +505,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"বাছনি কৰা ৱিজেটটো ৰাখক"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"লক স্ক্ৰীনৰ ৱিজেট"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"আপোনাৰ টেবলেটটো লক কৰি ৰাখিলেও যিকোনো লোকে আপোনাৰ লক স্ক্ৰীনত ৱিজেট চাব পাৰে।"</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ৱিজেট বাছনিৰ পৰা আঁতৰাওক"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"লক স্ক্ৰীন ৱিজেট"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"এটা ৱিজেট ব্যৱহাৰ কৰি কোনো এপ্ খুলিবলৈ, এয়া আপুনিয়েই বুলি সত্যাপন পৰীক্ষা কৰিব লাগিব। লগতে, মনত ৰাখিব যে যিকোনো লোকেই সেইবোৰ চাব পাৰে, আনকি আপোনাৰ টেবলেটটো লক হৈ থাকিলেও। কিছুমান ৱিজেট হয়তো আপোনাৰ লক স্ক্ৰীনৰ বাবে কৰা হোৱা নাই আৰু ইয়াত যোগ কৰাটো অসুৰক্ষিত হ’ব পাৰে।"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"বুজি পালোঁ"</string>
@@ -557,10 +562,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"এতিয়াই আৰম্ভ কৰক"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"কোনো জাননী নাই"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"কোনো নতুন জাননী নাই"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"জাননী কুলডাউন কৰাটো অন আছে"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"আপুনি একেলগে বহুতো জাননী পালে আপোনাৰ ডিভাইচটোৰ ভলিউম আৰু সতৰ্কবাৰ্তা স্বয়ংক্ৰিয়ভাৱে ২ মিনিটলৈকে কমোৱা হয়।"</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"অফ কৰক"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"পুৰণি জাননী চবলৈ আনলক কৰক"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"এই ডিভাইচটো আপোনাৰ অভিভাৱকে পৰিচালনা কৰে"</string>
@@ -1226,7 +1229,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"বিশ্বাসযোগ্যতা প্ৰমাণীকৰণৰ আৱশ্যক। বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰিবলৈ ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো স্পৰ্শ কৰক।"</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"চলি থকা ফ’ন কল"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"ম’বাইল ডেটা"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"সংযোজিত হৈ আছে"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"অস্থায়ীভাৱে সংযোগ কৰা হৈছে"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"বেয়া সংযোগ"</string>
@@ -1380,7 +1382,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"হ’ল"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"বঢ়িয়া!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"উভতি যাওক"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"উভতি যাবলৈ, টাচ্চপেডৰ যিকোনো স্থানত তিনিটা আঙুলি ব্যৱহাৰ কৰি বাওঁ বা সোঁফালে ছোৱাইপ কৰক।"</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"তিনিটা আঙুলি সোঁ আৰু বাওঁফালে লৰচৰ কৰা দেখুওৱা টাচ্চপেড"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"পিছফালৰ নিৰ্দেশৰ এনিমেশ্বন দেখুওৱা ডিভাইচ স্ক্ৰীন"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"কীব’ৰ্ডৰ বেকলাইট"</string>
@@ -1388,28 +1393,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"ঘৰৰ সা-সৰঞ্জামৰ নিয়ন্ত্ৰণ"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"স্ক্ৰীনছেভাৰ হিচাপে ক্ষিপ্ৰতাৰে ঘৰৰ সা-সৰঞ্জামৰ নিয়ন্ত্ৰণ এক্সেছ কৰক"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"আনডু কৰক"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"উভতি যাবলৈ টাচ্চপেডখনত তিনিটা আঙুলিৰে বাওঁ বা সোঁফালে ছোৱাইপ কৰক"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"গৃহপৃষ্ঠালৈ যাওক, টাচ্চপেডত তিনিটা আঙুলিৰে ওপৰলৈ ছোৱাইপ কৰক"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"শেহতীয়া এপ্সমূহ চাবলৈ টাচ্চপেডখনত তিনিটা আঙুলিৰে ওপৰলৈ ছোৱাইপ কৰি ধৰি ৰাখক"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"আপোনাৰ আটাইবোৰ এপ্ চাবলৈ আপোনাৰ কীব’ৰ্ডৰ কাৰ্য কীটোত টিপক"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"উভতি যাবলৈ আপোনাৰ টাচ্চপেড ব্যৱহাৰ কৰক"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"তিনিটা আঙুলি ব্যৱহাৰ কৰি বাওঁফাললৈ বা সোঁফাললৈ ছোৱাইপ কৰক। অধিক নিৰ্দেশ শিকিবলৈ টিপক।"</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"গৃহপৃষ্ঠালৈ যাবলৈ আপোনাৰ টাচ্চপেড ব্যৱহাৰ কৰক"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"তিনিটা আঙুলি ব্যৱহাৰ কৰি ওপৰলৈ ছোৱাইপ কৰক। অধিক নিৰ্দেশ শিকিবলৈ টিপক।"</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"শেহতীয়া এপ্সমূহ চাবলৈ আপোনাৰ টাচ্চপেড ব্যৱহাৰ কৰক"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"তিনিটা আঙুলি ব্যৱহাৰ কৰি ওপৰলৈ ছোৱাইপ কৰি ধৰি ৰাখক। অধিক নিৰ্দেশ শিকিবলৈ টিপক।"</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"আটাইবোৰ এপ্ চাবলৈ আপোনাৰ কীব’ৰ্ড ব্যৱহাৰ কৰক"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"যিকোনো সময়তে কাৰ্য কীটোত টিপক। অধিক নিৰ্দেশ শিকিবলৈ টিপক।"</string>
</resources>
diff --git a/packages/SystemUI/res/values-as/tiles_states_strings.xml b/packages/SystemUI/res/values-as/tiles_states_strings.xml
index fdd1f103..e978fe2 100644
--- a/packages/SystemUI/res/values-as/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-as/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"অফ আছে"</item>
<item msgid="4875147066469902392">"অন কৰা আছে"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"উপলব্ধ নহয়"</item>
- <item msgid="2004750556637773692">"অফ আছে"</item>
- <item msgid="8968530753931637871">"অন আছে"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"উপলব্ধ নহয়"</item>
<item msgid="5044688398303285224">"অফ আছে"</item>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index d748edc..d6abf07 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Performans"</string>
<string name="user_interface" msgid="3712869377953950887">"İstifadəçi interfeysi"</string>
<string name="thermal" msgid="6758074791325414831">"Termal"</string>
+ <string name="custom" msgid="3337456985275158299">"Fərdi"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Fərdi fəaliyyət izi ayarları"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Defoltu bərpa edin"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Birəlli rejim"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Eşitmə cihazları"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktiv"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritet rejimləri"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Hazırdır"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ayarlar"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Aktiv"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Deaktiv"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Seçdiyiniz siqnal, xatırladıcı, tədbir və zənglər istisna olmaqla səslər və vibrasiyalar Sizi narahat etməyəcək. Musiqi, video və oyunlar da daxil olmaqla oxutmaq istədiyiniz hər şeyi eşidəcəksiniz."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Siqnallar istisna olmaqla səslər və vibrasiyalar Sizi narahat etməyəcək. Musiqi, video və oyunlar da daxil olmaqla oxutmaq istədiyiniz hər şeyi eşidəcəksiniz."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Asta şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string>
<string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Kilid ekranındakı vidcetlər"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"İcma təlimatını başlatmaq üçün sola sürüşdürün"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Fərdiləşdirin"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Bağlayın"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"seçilmiş vidceti yerləşdirin"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Kilid ekranı vidcetləri"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Planşet kilidli olsa belə, hər kəs kilid ekranınızdakı vidcetlərə baxa bilər."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"vidcet seçimini silin"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Kilid ekranı vidcetləri"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Vidcetdən istifadə edərək tətbiqi açmaq üçün kimliyi doğrulamalısınız. Planşet kilidli olsa da, hər kəs vidcetlərə baxa bilər. Bəzi vidcetlər kilid ekranı üçün nəzərdə tutulmayıb və bura əlavə etmək təhlükəli ola bilər."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Anladım"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"İndi başlayın"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Heç bir bildiriş yoxdur"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Yeni bildiriş yoxdur"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Bildiriş gözləmə müddəti yanılıdır"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Eyni anda çox bildiriş aldıqda cihazın səs və xəbərdarlıqları avtomatik 2 dəqiqəyə qədər azalır."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Deaktiv edin"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Köhnə bildirişləri görmək üçün kilidi açın"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Bu cihaz valideyniniz tərəfindən idarə olunur"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Doğrulanma tələb olunur. Doğrulamaq üçün barmaq izi sensoruna toxunun."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Davam edən zəng"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobil data"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Qoşulub"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Müvəqqəti qoşulub"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Zəif bağlantı"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Hazırdır"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Əla!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Geri qayıdın"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Geri qayıtmaq üçün taçpedin istənilən yerində üç barmaqla sola və ya sağa çəkin."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Üç barmağın sağa və sola hərəkət etdiyini göstərən taçped"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Geri jesti üçün animasiya göstərən cihaz ekranı"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klaviatura işığı"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Ev nizamlayıcıları"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Ekran qoruyucu kimi ev nizamlayıcılarına tez giriş"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Geri qaytarın"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Geri qayıtmaq üçün taçpeddə üç barmağınızla sola və ya sağa çəkin"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Ana səhifəyə keçmək üçün taçpeddə üç barmağınızla yuxarı çəkin"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Son tətbiqlərə baxmaq üçün taçpeddə üç barmağınızla yuxarı çəkib saxlayın"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Bütün tətbiqlərə baxmaq üçün klaviaturada fəaliyyət açarını basın"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Geri qayıtmaq üçün taçped istifadə edin"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Üç barmaqla sola və ya sağa çəkin. Daha çox jest öyrənmək üçün toxunun."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Ana səhifəyə keçmək üçün taçped istifadə edin"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Üç barmaqla yuxarı çəkin. Daha çox jest öyrənmək üçün toxunun."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Son tətbiqlərə baxmaq üçün taçped istifadə edin"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Üç barmaq ilə yuxarı çəkib saxlayın. Daha çox jest öyrənmək üçün toxunun."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Bütün tətbiqlərə baxmaq üçün klaviatura istifadə edin"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"İstənilən vaxt fəaliyyət açarını basın. Daha çox jest öyrənmək üçün toxunun."</string>
</resources>
diff --git a/packages/SystemUI/res/values-az/tiles_states_strings.xml b/packages/SystemUI/res/values-az/tiles_states_strings.xml
index 678c94d..c24f402 100644
--- a/packages/SystemUI/res/values-az/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-az/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Deaktiv"</item>
<item msgid="4875147066469902392">"Aktiv"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Əlçatan deyil"</item>
- <item msgid="2004750556637773692">"Deaktiv"</item>
- <item msgid="8968530753931637871">"Aktiv"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Əlçatan deyil"</item>
<item msgid="5044688398303285224">"Deaktiv"</item>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 28144a6..307dcc0 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -141,7 +141,7 @@
<string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Želite da zaustavite prebacivanje?"</string>
<string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Trenutno prebacujete ceo ekran na: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Trenutno prebacujete ceo ekran na uređaj u blizini"</string>
- <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> se trenutno prebacuje na: <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> trenutno prebacujete na: <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
<string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> se trenutno prebacuje na uređaj u blizini"</string>
<string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"Trenutno prebacujete na: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"Trenutno prebacujete na uređaj u blizini"</string>
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Performanse"</string>
<string name="user_interface" msgid="3712869377953950887">"Korisnički interfejs"</string>
<string name="thermal" msgid="6758074791325414831">"Termalna kamera"</string>
+ <string name="custom" msgid="3337456985275158299">"Prilagođeno"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Podešavanja prilagođenog praćenja"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Vrati podrazumevano"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Režim jednom rukom"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Slušni aparati"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktivno"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritetni režimi"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gotovo"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Podešavanja"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Uključeno"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Isključeno"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Neće vas uznemiravati zvukovi i vibracije osim za alarme, podsetnike, događaje i pozivaoce koje navedete. I dalje ćete čuti sve što odaberete da pustite, uključujući muziku, video snimke i igre."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Neće vas uznemiravati zvukovi i vibracije osim za alarme. I dalje ćete čuti sve što odaberete da pustite, uključujući muziku, video snimke i igre."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sporo se puni • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja punjenja"</string>
<string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Puni se • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja punjenja"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Vidžeti na zaključanom ekranu"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Prevucite ulevo da biste započeli zajednički vodič"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prilagodite"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Odbaci"</string>
@@ -498,9 +507,8 @@
<string name="accessibility_action_label_remove_widget" msgid="3373779447448758070">"uklonite vidžet"</string>
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"postavite izabrani vidžet"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Vidžeti za zaključani ekran"</string>
- <string name="communal_widget_picker_description" msgid="490515450110487871">"Svi mogu da vide vedžete na zaključanom ekranu, čak i kada je tablet zaključan."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="communal_widget_picker_description" msgid="490515450110487871">"Svi mogu da vide vidžete na zaključanom ekranu, čak i kada je tablet zaključan."</string>
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"poništi izbor vidžeta"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Vidžeti za zaključani ekran"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Da biste otvorili aplikaciju koja koristi vidžet, treba da potvrdite da ste to vi. Imajte u vidu da svako može da ga vidi, čak i kada je tablet zaključan. Neki vidžeti možda nisu namenjeni za zaključani ekran i možda nije bezbedno da ih tamo dodate."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Važi"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Započni"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Nema obaveštenja"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Nema novih obaveštenja"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Utišavanje obaveštenja je uključeno"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Zvuk i broj upozorenja na uređaju se automatski smanjuju na 2 minuta kada dobijete previše obaveštenja."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Isključi"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Otključajte za starija obaveštenja"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Ovim uređajem upravlja roditelj"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Potrebna je potvrda identiteta. Dodirnite senzor za otisak prsta da biste potvrdili identitet."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Aktuelni telefonski poziv"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilni podaci"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Privremeno povezano"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Veza je loša"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gotovo"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Odlično!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Nazad"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Da biste se vratili, prevucite ulevo ili udesno sa tri prsta bilo gde na tačpedu."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Tačped sa prikazom tri prsta koji se pomeraju udesno i ulevo"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ekran uređaja sa prikazom animacije pokreta za nazad"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Pozadinsko osvetljenje tastature"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrole za dom"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Brz pristup kontrolama za dom kao čuvaru ekrana"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Opozovi"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Da biste se vratili, prevucite ulevo ili udesno sa tri prsta na tačpedu"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Da biste otišli na početni ekran, prevucite nagore sa tri prsta na tačpedu"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Da biste pregledali nedavne aplikacije, prevucite nagore i zadržite sa tri prsta na tačpedu"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Da biste pogledali sve aplikacije, pritisnite taster radnji na tastaturi"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Koristite tačped da biste se vratili"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Prevucite ulevo ili udesno sa tri prsta. Dodirnite da biste videli više pokreta."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Koristite tačped da biste otišli na početni ekran"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Prevucite nagore sa tri prsta. Dodirnite da biste videli više pokreta."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Koristite tačped da biste pregledali nedavne aplikacije"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Prevucite nagore i zadržite sa tri prsta. Dodirnite da biste videli više pokreta."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Koristite tastaturu da biste pregledali sve aplikacije"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pritisnite taster radnji u bilo kom trenutku. Dodirnite da biste videli više pokreta."</string>
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml b/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml
index be48b3b..df0b786 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Isključeno"</item>
<item msgid="4875147066469902392">"Uključeno"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Nedostupno"</item>
- <item msgid="2004750556637773692">"Isključeno"</item>
- <item msgid="8968530753931637871">"Uključeno"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Nedostupno"</item>
<item msgid="5044688398303285224">"Isključeno"</item>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index eaa7c38c..0580d7e 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Прадукцыйнасць"</string>
<string name="user_interface" msgid="3712869377953950887">"Карыстальніцкі інтэрфейс"</string>
<string name="thermal" msgid="6758074791325414831">"Тэрмальныя паказчыкі"</string>
+ <string name="custom" msgid="3337456985275158299">"Карыстальніцкае значэнне"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Карыстальніцкія налады трасіроўкі"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Аднавіць стандартнае значэнне"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Рэжым кіравання адной рукой"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слыхавыя апараты"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Актыўныя"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Прыярытэтныя рэжымы"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Гатова"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Налады"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Уключана"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Выключана"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Вас не будуць турбаваць гукі і вібрацыя, за выключэннем будзільнікаў, напамінаў, падзей і выбраных вамі абанентаў. Вы будзеце чуць усё, што ўключыце, у тым ліку музыку, відэа і гульні."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Вас не будуць турбаваць гукі і вібрацыя, за выключэннем будзільнікаў. Вы будзеце чуць усё, што ўключыце, у тым ліку музыку, відэа і гульні."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе павольная зарадка • Поўны зарад праз <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> • Ідзе зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Віджэты на экране блакіроўкі"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Правядзіце пальцам па экране ўлева, каб азнаёміцца з дапаможнікам"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Наладзіць"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Закрыць"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"размясціць выбраны віджэт"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Віджэты на экране блакіроўкі"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Віджэты на экране блакіроўкі будуць бачныя, нават калі планшэт заблакіраваны."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"скасаваць выбар віджэта"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Віджэты на экране блакіроўкі"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Каб адкрыць праграму з дапамогай віджэта, вам неабходна будзе пацвердзіць сваю асобу. Таксама памятайце, што такія віджэты могуць пабачыць іншыя людзі, нават калі экран планшэта заблакіраваны. Некаторыя віджэты могуць не падыходзіць для выкарыстання на экране блакіроўкі, і дадаваць іх сюды можа быць небяспечна."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Зразумела"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Пачаць зараз"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Апавяшчэнняў няма"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Няма новых апавяшчэнняў"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Зніжэнне гучнасці апавяшчэнняў уключана"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Калі адначасова прыходзіць шмат апавяшчэнняў, гук прылады і абвестак зніжаецца на час да 2 хвілін."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Выключыць"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Разблакіруйце, каб убачыць усе апавяшчэнні"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Гэта прылада знаходзіцца пад кантролем бацькоў"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Патрабуецца аўтэнтыфікацыя. Дакраніцеся да сканера адбіткаў пальцаў."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Бягучы тэлефонны выклік"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Мабільная перадача даных"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Падключана"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Падключана часова"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Нестабільнае падключэнне"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Гатова"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Цудоўна!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Каб вярнуцца на папярэдні экран, правядзіце трыма пальцамі ўлева або ўправа ў любым месцы сэнсарнай панэлі."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Паказваецца, як на сэнсарнай панэлі тры пальцы рухаюцца ўправа і ўлева"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"На экране прылады паказваецца анімацыя жэста \"Назад\""</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Падсветка клавіятуры"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Кіраванне домам"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Хуткі доступ да кіравання домам на застаўцы"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Адрабіць"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Каб вярнуцца, правядзіце па сэнсарнай панэлі трыма пальцамі ўлева ці ўправа"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Каб вярнуцца на галоўны экран, правядзіце па сэнсарнай панэлі трыма пальцамі ўверх"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Для прагляду нядаўніх праграм правядзіце па сэнсарнай панэлі трыма пальцамі ўверх і затрымайцеся"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Каб праглядзець усе праграмы, націсніце на клавішу дзеяння на клавіятуры"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Выкарыстайце сэнсарную панэль для вяртання"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Правядзіце ўлева ці ўправа трыма пальцамі. Націсніце, каб азнаёміцца з іншымі жэстамі."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Выкарыстайце сэнсарную панэль для вяртання на галоўны экран"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Правядзіце трыма пальцамі ўверх. Націсніце, каб азнаёміцца з іншымі жэстамі."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Выкарыстайце сэнсарную панэль, каб праглядзець нядаўнія праграмы"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Правядзіце трыма пальцамі ўверх і затрымайце пальцы. Націсніце, каб азнаёміцца з іншымі жэстамі."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Выкарыстайце клавіятуру для прагляду ўсіх праграм"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Можна націснуць на клавішу дзеяння ў любы момант. Націсніце, каб азнаёміцца з іншымі жэстамі."</string>
</resources>
diff --git a/packages/SystemUI/res/values-be/tiles_states_strings.xml b/packages/SystemUI/res/values-be/tiles_states_strings.xml
index aea701a..33e704c 100644
--- a/packages/SystemUI/res/values-be/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-be/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Выключана"</item>
<item msgid="4875147066469902392">"Уключана"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Недаступна"</item>
- <item msgid="2004750556637773692">"Выключана"</item>
- <item msgid="8968530753931637871">"Уключана"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Недаступна"</item>
<item msgid="5044688398303285224">"Выключана"</item>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index f515ea0..dfa9598 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Ефективност"</string>
<string name="user_interface" msgid="3712869377953950887">"Потребителски интерфейс"</string>
<string name="thermal" msgid="6758074791325414831">"Термално"</string>
+ <string name="custom" msgid="3337456985275158299">"Персонализирано"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Настройки за персонализираната следа"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Възстановяване на стандартната настройка"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Режим за работа с една ръка"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слухови апарати"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Активно"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Приоритетни режими"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Готово"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Настройки"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Вкл."</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Изкл."</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Няма да бъдете обезпокоявани от звуци и вибрирания освен от будилници, напомняния, събития и обаждания от посочени от вас контакти. Пак ще чувате всичко, което изберете да се пусне, включително музика, видеоклипове и игри."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Няма да бъдете обезпокоявани от звуци и вибрирания освен от будилници. Ще чувате обаче всичко, което изберете пуснете, включително музика, видеоклипове и игри."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се бавно • <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> • Зарежда се • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Приспособления на заключения екран"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Прекарайте пръст наляво, за да стартирате общия урок"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Персонализиране"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Отхвърляне"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"поставяне на избраното приспособление"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Приспособления за заключения екран"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Всеки ще вижда приспособленията на закл. екран дори ако таблетът ви е заключен."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"премахване на избора от приспособлението"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Приспособления за заключения екран"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"За да отворите дадено приложение посредством приспособление, ще трябва да потвърдите, че това сте вие. Също така имайте предвид, че всеки ще вижда приспособленията дори когато таблетът ви е заключен. Възможно е някои от тях да не са предназначени за заключения екран и добавянето им на него може да е опасно."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Разбрах"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Стартиране сега"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Няма известия"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Няма нови известия"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Изчакването за известията е включено"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Силата на звука и сигналите на у-вото се намаляват за до 2 минути, когато получавате твърде много известия наведнъж."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Изключване"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Отключете за достъп до по-стари известия"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Това устройство се управлява от родителя ви"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Изисква се удостоверяване на самоличността. За целта докоснете сензора за отпечатъци."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Текущо телефонно обаждане"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилни данни"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Свързано"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Установена е временна връзка"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Слаба връзка"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Отлично!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"За да се върнете назад, прекарайте три пръста наляво или надясно по сензорния панел."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Сензорен панел, върху който три пръста се движат надясно и наляво"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Екран на устройство, показващ анимация за жеста за връщане назад"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Подсветка на клавиатурата"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Контроли за дома"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Достъп до контролите за дома ви като скрийнсейвър"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Отмяна"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"За да се върнете назад, плъзнете три пръста наляво или надясно по сензорния панел"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"За да преминете към началния екран, плъзнете нагоре по сензорния панел с три пръста"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"За да прегледате скорошните приложения, плъзнете нагоре по сензорния панел с три пръста и задръжте"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"За да прегледате всичките си приложения, натиснете клавиша за действия на клавиатурата си"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Използвайте сензорния панел, за да се върнете назад"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Плъзнете три пръста наляво или надясно. Докоснете, за да научите повече жестове."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Използвайте сензорния панел, за да преминете към началния екран"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Плъзнете нагоре с три пръста. Докоснете, за да научите повече жестове."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Използвайте сензорния панел, за да прегледате скорошните приложения"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Плъзнете нагоре с три пръста и задръжте. Докоснете, за да научите повече жестове."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Използвайте клавиатурата, за да прегледате всички приложения"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Натиснете клавиша за действия по всяко време. Докоснете, за да научите повече жестове."</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/tiles_states_strings.xml b/packages/SystemUI/res/values-bg/tiles_states_strings.xml
index 0258d27..e2fd653 100644
--- a/packages/SystemUI/res/values-bg/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-bg/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Изкл."</item>
<item msgid="4875147066469902392">"Вкл."</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Не е налице"</item>
- <item msgid="2004750556637773692">"Изкл."</item>
- <item msgid="8968530753931637871">"Вкл."</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Не е налице"</item>
<item msgid="5044688398303285224">"Изкл."</item>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 2634892..3f6c269 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"পারফর্ম্যান্স"</string>
<string name="user_interface" msgid="3712869377953950887">"ইউজার ইন্টারফেস"</string>
<string name="thermal" msgid="6758074791325414831">"থার্মাল"</string>
+ <string name="custom" msgid="3337456985275158299">"কাস্টম"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"কাস্টম ট্রেস সেটিংস"</string>
+ <string name="restore_default" msgid="5259420807486239755">"ডিফল্ট সেটিং ফিরিয়ে আনুন"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"এক হাতে ব্যবহার করার মোড"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"হিয়ারিং ডিভাইস"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"অ্যাক্টিভ"</string>
@@ -431,6 +434,12 @@
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"সেটিংস"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"চালু আছে"</string>
<string name="zen_mode_off" msgid="1736604456618147306">"বন্ধ আছে"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
+ <skip />
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
+ <skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"অ্যালার্ম, রিমাইন্ডার, ইভেন্ট, এবং আপনার নির্দিষ্ট করে দেওয়া ব্যক্তিদের কল ছাড়া অন্য কোনও আওয়াজ বা ভাইব্রেশন হবে না। তবে সঙ্গীত, ভিডিও, এবং গেম সহ আপনি যা কিছু চালাবেন তার আওয়াজ শুনতে পাবেন।"</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"অ্যালার্ম ছাড়া অন্য কোনও আওয়াজ বা ভাইব্রেশন হবে না। তবে সঙ্গীত, ভিডিও, এবং গেম সহ আপনি যা কিছু চালাবেন তার আওয়াজ শুনতে পাবেন।"</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"কাস্টমাইজ করুন"</string>
@@ -469,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ধীরে চার্জ হচ্ছে • পুরো চার্জ হতে <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> • চার্জ হচ্ছে • পুরো চার্জ হতে আরও <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> সময় লাগবে"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"লক স্ক্রিনে উইজেট"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"কমিউনিটি টিউটোরিয়াল চালু করতে বাঁদিকে সোয়াইপ করুন"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"কাস্টমাইজ করুন"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"বাতিল করুন"</string>
@@ -554,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"এখন শুরু করুন"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"কোনও বিজ্ঞপ্তি নেই"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"নতুন কোনও বিজ্ঞপ্তি নেই"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"নোটিফিকেশন কুলডাউন চালু আছে"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"আপনি একসঙ্গে খুব বেশি বিজ্ঞপ্তি পেলে আপনার ডিভাইসের ভলিউম এবং সতর্কবার্তা সর্বাধিক ২ মিনিটের জন্য অটোমেটিক কমে যায়।"</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"বন্ধ করুন"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"পুরনো বিজ্ঞপ্তি দেখতে আনলক করুন"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"আপনার অভিভাবক এই ডিভাইস ম্যানেজ করেন"</string>
@@ -1223,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"যাচাইকরণ করতে হবে। যাচাইকরণ করতে আঙুলের ছাপের সেন্সরে টাচ করুন।"</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ব্যবহারকারী এখন ফোনে কথা বলছেন"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"মোবাইল ডেটা"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"কানেক্ট করা আছে"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"সাময়িকভাবে কানেক্ট করা হয়েছে"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"খারাপ কানেকশন"</string>
@@ -1377,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"হয়ে গেছে"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"অসাধারণ!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ফিরে যান"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"ফিরে যেতে, টাচপ্যাডের যেকোনও জায়গায় তিনটি আঙুল দিয়ে ডান বা বাঁদিকে সোয়াইপ করুন।"</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"টাচপ্যাডে, তিনটি আঙুল ডান ও বাঁদিকে সরানো দেখানো হচ্ছে"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"ডিভাইসের স্ক্রিনে ফিরে যাওয়ার জেসচারের অ্যানিমেশন দেখানো হচ্ছে"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"কীবোর্ড ব্যাকলাইট"</string>
diff --git a/packages/SystemUI/res/values-bn/tiles_states_strings.xml b/packages/SystemUI/res/values-bn/tiles_states_strings.xml
index 4935f32..6e4dfbf 100644
--- a/packages/SystemUI/res/values-bn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-bn/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"বন্ধ আছে"</item>
<item msgid="4875147066469902392">"চালু আছে"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"উপলভ্য নেই"</item>
- <item msgid="2004750556637773692">"বন্ধ আছে"</item>
- <item msgid="8968530753931637871">"চালু আছে"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"উপলভ্য নেই"</item>
<item msgid="5044688398303285224">"বন্ধ আছে"</item>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 08052a4..2bc13c0 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Performanse"</string>
<string name="user_interface" msgid="3712869377953950887">"Korisnički interfejs"</string>
<string name="thermal" msgid="6758074791325414831">"Termalno"</string>
+ <string name="custom" msgid="3337456985275158299">"Prilagođeno"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Prilagodite postavke traga"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Vrati zadano"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Način rada jednom rukom"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Slušni aparati"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktivno"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritetni načini rada"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gotovo"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Postavke"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Uključeno"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Isključeno"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Neće vas ometati zvukovi i vibracije, osim alarma, podsjetnika, događaja i pozivalaca koje odredite. I dalje ćete čuti sve što ste odabrali za reprodukciju, uključujući muziku, videozapise i igre."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Neće vas ometati zvukovi i vibracije, osim alarma. I dalje ćete čuti sve što izaberete za reprodukciju, uključujući muziku, videozapise i igre."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sporo punjenje • Potpuna napunjenost 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> • Punjenje • Potpuna napunjenost za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Vidžeti na zaključanom ekranu"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Prevucite ulijevo da pokrenete zajednički vodič"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prilagodite"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Odbaci"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"postavljanje odabranog vidžeta"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Vidžeti na zaključanom ekranu"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Svi mogu pregledati vidžete na zaključanom ekranu, čak i ako je tablet zaključan."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"poništavanje odabira vidžeta"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Vidžeti zaključanog ekrana"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Da otvorite aplikaciju pomoću vidžeta, morat ćete potvrditi identitet. Također imajte na umu da ih svako može pregledati, čak i ako je tablet zaključan. Neki vidžeti možda nisu namijenjeni za vaš zaključani ekran i njihovo dodavanje ovdje možda nije sigurno."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Razumijem"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Započni odmah"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Nema obavještenja"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Nema novih obavještenja"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Stišavanje obavještenja je uključeno"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Jačina zvuka uređaja i obavještenja se automatski stišavaju do 2 minute kada odjednom dobijete previše obavještenja."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Isključi"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Otključajte da vidite starija obavještenja"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Ovim uređajem upravlja tvoj roditelj"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Potrebna je autentifikacija. Dodirnite senzor za otisak prsta da autentificirate."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonski poziv u toku"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Prijenos podataka na mobilnoj mreži"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Privremeno povezano"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Slaba veza"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gotovo"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Sjajno!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Nazad"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Da se vratite, prevucite ulijevo ili udesno s tri prsta bilo gdje na dodirnoj podlozi."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Dodirna podloga prikazuje tri prsta koji se pomjeraju desno-lijevo"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ekran uređaja pokazuje animaciju pokreta unazad"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Pozadinsko osvjetljenje tastature"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrole za dom"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Brzo pristupajte kontrolama za dom putem čuvara ekrana"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Poništi"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Da se vratite, prevucite ulijevo ili udesno s tri prsta na dodirnoj podlozi"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Da se vratite na početnu stranicu, prevucite nagore s tri prsta na dodirnoj podlozi"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Da pregledate nedavne aplikacije, prevucite nagore i zadržite s tri prsta na dodirnoj podlozi"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Da pregledate sve aplikacije, pritisnite tipku radnji na tastaturi"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Koristite dodirnu podlogu da se vratite"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Prevucite ulijevo ili udesno s tri prsta. Dodirnite da saznate za više pokreta."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Koristite dodirnu podlogu da se vratite na početnu stranicu"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Prevucite nagore s tri prsta. Dodirnite da saznate za više pokreta."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Koristite dodirnu podlogu da pregledate nedavne aplikacije"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Prevucite nagore i zadržite s tri prsta. Dodirnite da saznate za više pokreta."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Koristite tastaturu da pregledate sve aplikacije"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pritisnite tipku radnji bilo kada. Dodirnite da saznate za više pokreta."</string>
</resources>
diff --git a/packages/SystemUI/res/values-bs/tiles_states_strings.xml b/packages/SystemUI/res/values-bs/tiles_states_strings.xml
index be48b3b..df0b786 100644
--- a/packages/SystemUI/res/values-bs/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-bs/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Isključeno"</item>
<item msgid="4875147066469902392">"Uključeno"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Nedostupno"</item>
- <item msgid="2004750556637773692">"Isključeno"</item>
- <item msgid="8968530753931637871">"Uključeno"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Nedostupno"</item>
<item msgid="5044688398303285224">"Isključeno"</item>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index a76ee9f..a9ab9fc 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Rendiment"</string>
<string name="user_interface" msgid="3712869377953950887">"Interfície d\'usuari"</string>
<string name="thermal" msgid="6758074791325414831">"Tèrmic"</string>
+ <string name="custom" msgid="3337456985275158299">"Personalitzat"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Configuració de traça personalitzada"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Restaura la configuració predeterminada"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Mode d\'una mà"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Audiòfons"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Actiu"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modes prioritaris"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Fet"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configuració"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Activat"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Desactivat"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"No t\'interromprà cap so ni cap vibració, tret dels de les alarmes, recordatoris, esdeveniments i trucades de les persones que especifiquis. Continuaràs sentint tot allò que decideixis reproduir, com ara música, vídeos i jocs."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"No t\'interromprà cap so ni cap vibració, tret dels de les alarmes. Continuaràs sentint tot allò que decideixis reproduir, com ara música, vídeos i jocs."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregant lentament • Es completarà d\'aquí a <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> • S\'està carregant • Es completarà d\'aquí a <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets a la pantalla de bloqueig"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Llisca cap a l\'esquerra per iniciar el tutorial de la comunitat"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalitza"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Ignora"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"col·loca el widget seleccionat"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgets de la pantalla de bloqueig"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Tothom pot veure widgets a la pantalla de bloqueig, fins i tot amb la tauleta bloquejada."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"desselecciona el widget"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets de la pantalla de bloqueig"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Per obrir una aplicació utilitzant un widget, necessitaràs verificar la teva identitat. També has de tenir en compte que qualsevol persona pot veure els widgets, fins i tot quan la tauleta està bloquejada. És possible que alguns widgets no estiguin pensats per a la pantalla de bloqueig i que no sigui segur afegir-los-hi."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Entesos"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Comença ara"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"No hi ha cap notificació"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"No hi ha cap notificació nova"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"La moderació de notificacions està activada"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"El volum i les alertes del dispositiu es redueixen automàticament durant 2 minuts quan reps massa notificacions alhora."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Desactiva"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueja per veure notif. anteriors"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Els teus pares gestionen aquest dispositiu"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticació necessària. Toca el sensor d\'empremtes digitals per autenticar-te."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Trucada en curs"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Dades mòbils"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Connectat"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connexió temporal"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Connexió feble"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Fet"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Ben fet!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Torna"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Per tornar enrere, llisca cap a l\'esquerra o cap a la dreta amb tres dits en qualsevol lloc del ratolí tàctil."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Ratolí tàctil que mostra tres dits que es mouen cap a la dreta i cap a l\'esquerra"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Pantalla del dispositiu que mostra l\'animació del gest per anar enrere"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroil·luminació del teclat"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Controls de la llar"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Utilitza controls de la llar com a estalvi de pantalla"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Desfés"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Per tornar enrere, llisca tres dits cap a l\'esquerra o cap a la dreta al ratolí tàctil"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Per anar a la pantalla d\'inici, llisca tres dits cap amunt al ratolí tàctil"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Per veure les aplicacions recents, llisca cap amunt amb tres dits i mantén premut al ratolí tàctil"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Per veure totes les aplicacions, prem la tecla d\'acció al teclat"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Utilitza el ratolí tàctil per tornar enrere"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Fes lliscar tres dits cap a l\'esquerra o cap a la dreta. Toca per aprendre més gestos."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Utilitza el ratolí tàctil per anar a la pantalla d\'inici"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Llisca tres dits cap amunt. Toca per aprendre més gestos."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Utilitza el ratolí tàctil per veure les aplicacions recents"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Llisca cap amunt amb tres dits i mantén premut. Toca per aprendre més gestos."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Utilitza el teclat per veure totes les aplicacions"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Prem la tecla d\'acció en qualsevol moment. Toca per aprendre més gestos."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/tiles_states_strings.xml b/packages/SystemUI/res/values-ca/tiles_states_strings.xml
index d11dd32..67eb853 100644
--- a/packages/SystemUI/res/values-ca/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ca/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Desactivat"</item>
<item msgid="4875147066469902392">"Activat"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"No disponible"</item>
- <item msgid="2004750556637773692">"Desactivat"</item>
- <item msgid="8968530753931637871">"Activat"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"No disponible"</item>
<item msgid="5044688398303285224">"Desactivat"</item>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 12ef55c..194057a 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Výkon"</string>
<string name="user_interface" msgid="3712869377953950887">"Uživatelské rozhraní"</string>
<string name="thermal" msgid="6758074791325414831">"Termovize"</string>
+ <string name="custom" msgid="3337456985275158299">"Vlastní"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Vlastní nastavení trasování"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Obnovit výchozí"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Režim jedné ruky"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Naslouchátka"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktivní"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Režimy priority"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Hotovo"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Nastavení"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Zapnuto"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Vypnuto"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Nebudou vás rušit zvuky ani vibrace s výjimkou budíků, upozornění, událostí a volajících, které zadáte. Nadále uslyšíte veškerý obsah, který si sami pustíte (např. hudba, videa nebo hry)."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Nebudou vás rušit zvuky ani vibrace s výjimkou budíků. Nadále uslyšíte veškerý obsah, který si sami pustíte (např. hudba, videa nebo hry)."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Pomalé nabíjení • Plně nabito 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> • Nabíjení • Plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgety na obrazovce uzamčení"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Přejetím doleva spustíte komunitní výukový program"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Přizpůsobit"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Zavřít"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"umístit vybraný widget"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgety na obrazovce uzamčení"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Widgety na obrazovce uzamčení může zobrazit kdokoli, i když je tablet uzamčen."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"zrušit výběr widgetu"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgety na obrazovce uzamčení"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"K otevření aplikace pomocí widgetu budete muset ověřit svou totožnost. Také mějte na paměti, že widgety uvidí kdokoli, i když tablet bude uzamčen. Některé widgety nemusí být pro obrazovku uzamčení určeny a nemusí být bezpečné je na ni přidat."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Rozumím"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Spustit"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Žádná oznámení"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Žádná nová oznámení"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Je zapnuté zeslabení oznámení"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Když dostanete příliš mnoho oznámení najednou, až na dvě minuty se sníží hlasitost zařízení a oznámení se omezí."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Vypnout"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Starší oznámení se zobrazí po odemknutí"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Toto zařízení spravuje rodič"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Je vyžadováno ověření. Dotkněte se snímače otisků prstů."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Probíhající hovor"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilní data"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Připojeno"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Dočasně připojeno"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Nekvalitní připojení"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Hotovo"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Výborně!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Zpět"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Pokud se chcete vrátit zpět, stačí kdekoli na touchpadu přejet třemi prsty doleva nebo doprava."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad se třemi prsty, které se pohybují doprava a doleva"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Obrazovka zařízení s animaci gesta k vrácení zpět"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Podsvícení klávesnice"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Ovládání domácnosti"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Rychlý přístup k funkcím, jako je spořič obrazovky"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Vrátit zpět"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Pokud se chcete vrátit zpět, přejeďte po touchpadu třemi prsty doleva nebo doprava"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Pokud se chcete vrátit domů, přejeďte po touchpadu třemi prsty nahoru"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Pokud chcete zobrazit poslední aplikace, přejeďte na touchpadu třemi prsty nahoru a podržte je"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Pokud chcete zobrazit všechny aplikace, stiskněte na klávesnici akční klávesu"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Návrat zpět pomocí touchpadu"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Přejeďte třemi prsty doleva nebo doprava. Další gesta zjistíte klepnutím."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Návrat domů pomocí touchpadu"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Přejeďte třemi prsty nahoru. Další gesta zjistíte klepnutím."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Zobrazení posledních aplikací pomocí touchpadu"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Přejeďte třemi prsty nahoru a podržte je. Další gesta zjistíte klepnutím."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Zobrazení všech aplikací pomocí klávesnice"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Kdykoli stiskněte akční klávesu. Další gesta zjistíte klepnutím."</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/tiles_states_strings.xml b/packages/SystemUI/res/values-cs/tiles_states_strings.xml
index 71c9569..ae533a8 100644
--- a/packages/SystemUI/res/values-cs/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-cs/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Vypnuto"</item>
<item msgid="4875147066469902392">"Zapnuto"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Nedostupné"</item>
- <item msgid="2004750556637773692">"Vypnuto"</item>
- <item msgid="8968530753931637871">"Zapnuto"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Nedostupné"</item>
<item msgid="5044688398303285224">"Vypnuto"</item>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index ef9ef95..ba1babf 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -131,7 +131,7 @@
<string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Du optager i øjeblikket <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Stop optagelse"</string>
<string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"Skærmen deles"</string>
- <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Stop skærmdelingen?"</string>
+ <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Vil du stoppe skærmdelingen?"</string>
<string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Du deler i øjeblikket hele skærmen med <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string>
<string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Du deler i øjeblikket hele skærmen med en app"</string>
<string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Du deler i øjeblikket <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string>
@@ -218,13 +218,13 @@
<string name="biometric_re_enroll_notification_content" msgid="8685925877186288180">"Dette er påkrævet for at forbedre sikkerheden og ydeevnen"</string>
<string name="fingerprint_re_enroll_notification_title" msgid="4539432429683916604">"Konfigurer fingeroplåsning igen"</string>
<string name="fingerprint_re_enroll_notification_name" msgid="630798657797645704">"Fingeroplåsning"</string>
- <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Konfigurer fingeroplåsning"</string>
+ <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Konfigurer fingeroplåsning"</string>
<string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"Hvis du vil konfigurere fingeroplåsning igen, bliver dine nuværende fingeraftryksbilleder og -modeller slettet.\n\nNår de er slettet, skal du konfigurere fingeroplåsning igen for at bruge dit fingeraftryk til at låse din telefon op eller verificere din identitet."</string>
<string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"Hvis du vil konfigurere fingeroplåsning igen, bliver dine nuværende fingeraftryksbilleder og -modeller slettet.\n\nNår de er slettet, skal du konfigurere fingeroplåsning igen for at bruge dit fingeraftryk til at låse din telefon op eller verificere din identitet."</string>
<string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"Fingeroplåsning kunne ikke konfigureres. Gå til Indstillinger for at prøve igen."</string>
<string name="face_re_enroll_notification_title" msgid="1850838867718410520">"Konfigurer ansigtsoplåsning igen"</string>
<string name="face_re_enroll_notification_name" msgid="7384545252206120659">"Ansigtsoplåsning"</string>
- <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"Konfigurer ansigtsoplåsning"</string>
+ <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"Konfigurer ansigtsoplåsning"</string>
<string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"Hvis du vil konfigurere ansigtsoplåsning igen, bliver din nuværende ansigtsmodel slettet.\n\nDu skal konfigurere funktionen igen for at bruge ansigtsgenkendelse til at låse din telefon op."</string>
<string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Ansigtsoplåsning kunne ikke konfigureres. Gå til Indstillinger for at prøve igen."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Sæt fingeren på fingeraftrykssensoren"</string>
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Ydeevne"</string>
<string name="user_interface" msgid="3712869377953950887">"Brugerflade"</string>
<string name="thermal" msgid="6758074791325414831">"Termisk"</string>
+ <string name="custom" msgid="3337456985275158299">"Tilpas"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Tilpas indstillinger for registrering"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Gendan standard"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Enhåndstilstand"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Høreapparater"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktivt"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Tilstande med prioritet"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Udfør"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Indstillinger"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Til"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Fra"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Du bliver ikke forstyrret af lyde eller vibrationer, undtagen fra alarmer, påmindelser, begivenheder og opkald fra udvalgte personer, du selv angiver. Du kan stadig høre alt, du vælger at afspille, f.eks. musik, videoer og spil."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Du bliver ikke forstyrret af lyde eller vibrationer, undtagen fra alarmer. Du kan stadig høre alt, du vælger at afspille, f.eks. musik, videoer og spil."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader langsomt • Fuldt opladet om <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> • Oplader • Fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets på låseskærmen"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Stryg mod venstre for at starte den fælles vejledning"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Tilpas"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Luk"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"placer valgt widget"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgets på låseskærmen"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Alle kan se widgets på din låseskærm, også selvom din tablet er låst."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"fjern markering af widget"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets på låseskærmen"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Hvis du vil åbne en app ved hjælp af en widget, skal du verificere din identitet. Husk også, at alle kan se dem, også når din tablet er låst. Nogle widgets er muligvis ikke beregnet til låseskærmen, og det kan være usikkert at tilføje dem her."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Start nu"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Ingen notifikationer"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Ingen nye notifikationer"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Dæmpning af notifikationer er aktiveret"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Enheden skruer automatisk ned for lydstyrken og minimerer underretninger på skærmen i op til 2 minutter, når du får for mange notifikationer på én gang."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Deaktiver"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Lås op for at se ældre notifikationer"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Denne enhed administreres af din forælder"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Godkendelse er påkrævet. Sæt fingeren på fingeraftrykssensoren for at godkende."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Igangværende telefonopkald"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobildata"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Forbundet"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Midlertidigt forbundet"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Dårlig forbindelse"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Udfør"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Sådan!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Gå tilbage"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Du kan gå tilbage ved at stryge mod venstre eller højre med tre fingre et vilkårligt sted på touchpladen."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchplade viser tre fingre, der bevæger sig til højre og venstre"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Enhedsskærm, der viser en animation, som demonstrerer, hvordan man går tilbage"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Tastaturets baggrundslys"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Hjemmestyring"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Tilgå hurtigt hjemmestyring via din pauseskærm"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Fortryd"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Du kan gå tilbage ved at stryge til venstre eller højre med tre fingre på touchpladen"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Du kan gå til startskærmen ved at stryge opad med tre fingre på touchpladen"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Du kan se nyligt brugte apps ved at stryge opad og holde tre fingre nede på touchpladen"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Du kan se alle dine apps ved at trykke på handlingstasten på dit tastatur"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Brug din touchplade til at gå tilbage"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Stryg til venstre eller højre med tre fingre. Tryk for at lære flere bevægelser."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Brug din touchplade til at gå til startskærmen"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Stryg opad med tre fingre. Tryk for at lære flere bevægelser."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Brug din touchplade til at se nyligt brugte apps"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Stryg opad, og hold tre fingre nede. Tryk for at lære flere bevægelser."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Brug dit tastatur til at se alle apps"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Tryk på handlingstasten når som helst. Tryk for at lære flere bevægelser."</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/tiles_states_strings.xml b/packages/SystemUI/res/values-da/tiles_states_strings.xml
index 9b11f52..2c3b053 100644
--- a/packages/SystemUI/res/values-da/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-da/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Fra"</item>
<item msgid="4875147066469902392">"Til"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Ikke tilgængelig"</item>
- <item msgid="2004750556637773692">"Fra"</item>
- <item msgid="8968530753931637871">"Til"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Ikke tilgængelig"</item>
<item msgid="5044688398303285224">"Fra"</item>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index c9b449d..62ede78 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Leistung"</string>
<string name="user_interface" msgid="3712869377953950887">"Benutzeroberfläche"</string>
<string name="thermal" msgid="6758074791325414831">"Überhitzung"</string>
+ <string name="custom" msgid="3337456985275158299">"Benutzerdefiniert"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Benutzerdefinierte Trace-Einstellungen"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Standard wiederherstellen"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Einhandmodus"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hörgeräte"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktiv"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritätsmodi"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Fertig"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Einstellungen"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"An"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Aus"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Klingeltöne und die Vibration werden deaktiviert, außer für Weckrufe, Erinnerungen, Termine sowie Anrufe von zuvor von dir festgelegten Personen. Du hörst jedoch weiterhin Sound, wenn du dir Musik anhörst, Videos ansiehst oder Spiele spielst."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Klingeltöne und die Vibration werden deaktiviert, außer für Weckrufe. Du hörst jedoch weiterhin Sound, wenn du dir Musik anhörst, Videos ansiehst oder Spiele spielst."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird langsam geladen • Voll in <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> • Wird geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets auf dem Sperrbildschirm"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Wische nach links, um das gemeinsame Tutorial zu starten"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Anpassen"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Schließen"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"ausgewähltes Widget in den Bearbeitungsmodus versetzen"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Sperrbildschirm-Widgets"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Jeder kann Widgets auf deinem Sperrbildschirm sehen, auch bei gesperrtem Tablet."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"Auswahl für Widget aufheben"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Sperrbildschirm-Widgets"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Wenn du eine App mit einem Widget öffnen möchtest, musst du deine Identität bestätigen. Beachte auch, dass jeder die Widgets sehen kann, auch wenn dein Tablet gesperrt ist. Einige Widgets sind möglicherweise nicht für den Sperrbildschirm vorgesehen, sodass es unsicher sein kann, sie hier hinzuzufügen."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Ok"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Jetzt starten"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Keine Benachrichtigungen"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Keine neuen Benachrichtigungen"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Verringern von Lautstärke und Vibration bei Benachrichtigungen ist an"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Wenn du in kurzer Zeit zu viele Benachrichtigungen erhältst, wird automatisch für bis zu 2 Minuten die Lautstärke des Geräts verringert und Benachrichtigungen werden reduziert."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Deaktivieren"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Für ältere Benachrichtigungen entsperren"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Dieses Gerät wird von deinen Eltern verwaltet"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentifizierung erforderlich. Tippe dazu einfach auf den Fingerabdrucksensor."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Aktiver Anruf"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile Daten"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Verbunden"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Vorübergehend verbunden"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Schwache Verbindung"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Fertig"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Gut gemacht!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Zurück"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Wenn du zurückgehen möchtest, wische an einer beliebigen Stelle des Touchpads mit drei Fingern nach links oder rechts."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad mit drei Fingern, die sich nach links und rechts bewegen"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Bildschirm zeigt eine Animation der Touch-Geste „Zurück“"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Tastaturbeleuchtung"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Smart-Home-Steuerung"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Smart-Home-Steuerung als Bildschirmschoner nutzen"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Rückgängig machen"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Wenn du zurückgehen möchtest, wische auf dem Touchpad mit drei Fingern nach links oder rechts"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Wenn du den Startbildschirm aufrufen möchtest, wische auf dem Touchpad mit drei Fingern nach oben"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Um zuletzt verwendete Apps aufzurufen, wische mit 3 Fingern nach oben und halte das Touchpad gedrückt"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Wenn du alle deine Apps aufrufen möchtest, drücke auf der Tastatur die Aktionstaste"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Über das Touchpad zurückgehen"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Wische mit drei Fingern nach links oder rechts. Tippe für mehr Infos zu Touch-Gesten."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Über das Touchpad zum Startbildschirm zurückkehren"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Wische mit drei Fingern nach oben. Tippe für mehr Infos zu Touch-Gesten."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Über das Touchpad zuletzt verwendete Apps aufrufen"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Wische mit 3 Fingern nach oben und halte das Touchpad gedrückt. Tippe für mehr Infos zu Touch-Gesten."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Über die Tastatur alle Apps aufrufen"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Du kannst jederzeit die Aktionstaste drücken. Tippe für mehr Infos zu Touch-Gesten."</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/tiles_states_strings.xml b/packages/SystemUI/res/values-de/tiles_states_strings.xml
index f27ac22..0606cc7 100644
--- a/packages/SystemUI/res/values-de/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-de/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Aus"</item>
<item msgid="4875147066469902392">"An"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Nicht verfügbar"</item>
- <item msgid="2004750556637773692">"Aus"</item>
- <item msgid="8968530753931637871">"An"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Nicht verfügbar"</item>
<item msgid="5044688398303285224">"Aus"</item>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 55c06d1..5025f6d 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -128,20 +128,20 @@
<string name="screenrecord_start_error" msgid="2200660692479682368">"Σφάλμα κατά την έναρξη της εγγραφής οθόνης"</string>
<string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"Να διακοπεί η εγγραφή;"</string>
<string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"Αυτή τη στιγμή εγγράφετε ολόκληρη την οθόνη σας"</string>
- <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Αυτή τη στιγμή εγγράφετε την <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Αυτή τη στιγμή εγγράφετε το <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Διακοπή εγγραφής"</string>
<string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"Γίνεται κοινοποίηση οθόνης"</string>
<string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Διακοπή κοινής χρήσης οθόνης;"</string>
- <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Αυτή τη στιγμή μοιράζεστε ολόκληρη την οθόνη σας με την <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string>
+ <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Αυτή τη στιγμή μοιράζεστε ολόκληρη την οθόνη σας με το <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string>
<string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Αυτή τη στιγμή μοιράζεστε ολόκληρη την οθόνη σας με μια εφαρμογή"</string>
- <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Αυτή τη στιγμή μοιράζεστε την <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string>
+ <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Αυτή τη στιγμή μοιράζεστε το <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string>
<string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"Αυτή τη στιγμή μοιράζεστε μια εφαρμογή"</string>
<string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"Διακοπή κοινής χρήσης"</string>
<string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"Μετάδοση οθόνης"</string>
<string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Τερματισμός μετάδοσης;"</string>
<string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Αυτή τη στιγμή μεταδίδετε ολόκληρη την οθόνη σας στη <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Αυτή τη στιγμή μεταδίδετε ολόκληρη την οθόνη σας σε μια συσκευή σε κοντινή απόσταση"</string>
- <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Αυτή τη στιγμή μεταδίδετε την <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> στη <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Αυτή τη στιγμή μεταδίδετε το <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> στο <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
<string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"Αυτή τη στιγμή μεταδίδετε την <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> σε μια συσκευή σε κοντινή απόσταση"</string>
<string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"Αυτή τη στιγμή κάνετε μετάδοση στη <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"Αυτή τη στιγμή κάνετε μετάδοση σε μια συσκευή σε κοντινή απόσταση"</string>
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Απόδοση"</string>
<string name="user_interface" msgid="3712869377953950887">"Διεπαφή χρήστη"</string>
<string name="thermal" msgid="6758074791325414831">"Θερμικό"</string>
+ <string name="custom" msgid="3337456985275158299">"Προσαρμοσμένο"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Ρυθμίσεις προσαρμοσμένου ίχνους"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Επαναφορά προεπιλογής"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Λειτουργία ενός χεριού"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Συσκευές ακοής"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Ενεργές"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Λειτουργίες προτεραιότητας"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Τέλος"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ρυθμίσεις"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Ενεργό"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Ανενεργό"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Δεν θα ενοχλείστε από ήχους και δονήσεις, παρά μόνο από ξυπνητήρια, υπενθυμίσεις, συμβάντα και καλούντες που έχετε καθορίσει. Θα εξακολουθείτε να ακούτε όλο το περιεχόμενο που επιλέγετε να αναπαραγάγετε, συμπεριλαμβανομένης της μουσικής, των βίντεο και των παιχνιδιών."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Δεν θα ενοχλείστε από ήχους και δονήσεις, παρά μόνο από ξυπνητήρια. Θα εξακολουθείτε να ακούτε όλο το περιεχόμενο που επιλέγετε να αναπαραγάγετε, συμπεριλαμβανομένης της μουσικής, των βίντεο και των παιχνιδιών."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Αργή φόρτιση • Πλήρης φόρτιση σε <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> • Φόρτιση • Πλήρης φόρτιση σε <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Γραφικά στοιχεία στην οθόνη κλειδώματος"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Σύρετε προς τα αριστερά για να ξεκινήσετε τον κοινόχρηστο οδηγό"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Προσαρμογή"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Παράβλεψη"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"τοποθέτηση επιλεγμένου γραφικού στοιχείου"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Γραφικά στοιχεία οθόνης κλειδώματος"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Όλοι μπορούν να δουν γραφικά στοιχεία στην οθόνη κλειδώματος, ακόμα και αν το tablet είναι κλειδωμένο."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"αποεπιλογή γραφικού στοιχείου"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Γραφικά στοιχεία οθόνης κλειδώματος"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Για να ανοίξετε μια εφαρμογή χρησιμοποιώντας ένα γραφικό στοιχείο, θα πρέπει να επαληθεύσετε την ταυτότητά σας. Επίσης, λάβετε υπόψη ότι η προβολή τους είναι δυνατή από οποιονδήποτε, ακόμα και όταν το tablet σας είναι κλειδωμένο. Ορισμένα γραφικά στοιχεία μπορεί να μην προορίζονται για την οθόνη κλειδώματος και η προσθήκη τους εδώ ενδέχεται να μην είναι ασφαλής."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Το κατάλαβα"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Έναρξη τώρα"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Δεν υπάρχουν ειδοποιήσεις"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Δεν υπάρχουν νέες ειδοποιήσεις"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Η περίοδος cooldown ειδοποιήσεων είναι ενεργή"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Αυτόματη μείωση έντασης ήχου συσκευής και ειδοποιήσεων για έως 2 λεπτά όταν λαμβάνετε πολλές ειδοποιήσεις ταυτόχρονα."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Απενεργοποίηση"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Ξεκλειδώστε για εμφάνιση παλαιότ. ειδοπ."</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Αυτή η συσκευή είναι διαχειριζόμενη από τον γονέα σου"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Απαιτείται έλεγχος ταυτότητας. Αγγίξτε τον αισθητήρα δακτυλικών αποτυπωμάτων για έλεγχο ταυτότητας."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Τηλεφωνική κλήση σε εξέλιξη"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Δεδομένα κινητής τηλεφωνίας"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Συνδέθηκε"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Προσωρινή σύνδεση"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Ασθενής σύνδεση"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Τέλος"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Μπράβο!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Επιστροφή"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Για επιστροφή, σύρετε προς τα αριστερά ή προς τα δεξιά χρησιμοποιώντας τρία δάχτυλα οπουδήποτε στην επιφάνεια αφής."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Επιφάνεια αφής στην οποία εμφανίζονται τρία δάχτυλα να κινούνται δεξιά και αριστερά"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Οθόνη συσκευής που εμφανίζει μια κινούμενη εικόνα σχετικά με την κίνηση επιστροφής"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Οπίσθιος φωτισμός πληκτρολογίου"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Οικιακοί έλεγχοι"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Γρήγ. πρόσβαση σε οικιακ. ελέγχους ως προφ. οθόνης"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Αναίρεση"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Για επιστροφή, σύρετε προς τα αριστερά ή τα δεξιά με τρία δάχτυλα στην επιφάνεια αφής"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Για μετάβαση στην αρχική οθόνη, σύρετε προς τα επάνω στην επιφάνεια αφής με τρία δάχτυλα"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Για πρόσφατες εφαρμογές, σαρώστε προς τα πάνω με τρία δάχτυλα και κρατήστε τα στην επιφάνεια αφής"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Για να δείτε όλες τις εφαρμογές, πιέστε το πλήκτρο ενέργειας στο πληκτρολόγιό σας"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Χρήση της επιφάνειας αφής για επιστροφή"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Σύρετε προς τα αριστερά ή τα δεξιά με τρία δάχτυλα. Πατήστε για να μάθετε περισσότερες κινήσεις."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Χρήση της επιφάνειας αφής για μετάβαση στην αρχική οθόνη"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Σύρετε προς τα πάνω με τρία δάχτυλα. Πατήστε για να μάθετε περισσότερες κινήσεις."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Χρήση της επιφάνειας αφής για προβολή πρόσφατων εφαρμογών"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Σύρετε προς τα πάνω με τρία δάχτυλα και μην τα σηκώσετε. Πατήστε για να δείτε περισσότερες κινήσεις."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Χρήση του πληκτρολογίου για προβολή όλων των εφαρμογών"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Πιέστε το πλήκτρο ενέργειας ανά πάσα στιγμή. Πατήστε για να μάθετε περισσότερες κινήσεις."</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/tiles_states_strings.xml b/packages/SystemUI/res/values-el/tiles_states_strings.xml
index 9db5c8f..d4545ff 100644
--- a/packages/SystemUI/res/values-el/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-el/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Ανενεργό"</item>
<item msgid="4875147066469902392">"Ενεργό"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Μη διαθέσιμο"</item>
- <item msgid="2004750556637773692">"Ανενεργό"</item>
- <item msgid="8968530753931637871">"Ενεργό"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Μη διαθέσιμο"</item>
<item msgid="5044688398303285224">"Ανενεργό"</item>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 23c3ff3..f2ba704 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Performance"</string>
<string name="user_interface" msgid="3712869377953950887">"User interface"</string>
<string name="thermal" msgid="6758074791325414831">"Thermal"</string>
+ <string name="custom" msgid="3337456985275158299">"Custom"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Custom trace settings"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Restore default"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"One-handed mode"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hearing devices"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Active"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Priority modes"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Done"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"On"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Off"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events and callers you specify. You\'ll still hear anything you choose to play including music, videos and games."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"You won\'t be disturbed by sounds and vibrations, except from alarms. You\'ll still hear anything you choose to play including music, videos and games."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <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> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets on lock screen"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Customise"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dismiss"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"place selected widget"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Lock screen widgets"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Anyone can view widgets on your lock screen, even if your tablet\'s locked."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"unselect widget"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Lock screen widgets"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"To open an app using a widget, you\'ll need to verify that it\'s you. Also, bear in mind that anyone can view them, even when your tablet\'s locked. Some widgets may not have been intended for your lock screen and may be unsafe to add here."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Got it"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Start now"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"No notifications"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"No new notifications"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Notification cooldown is on"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Your device volume and alerts are reduced automatically for up to 2 minutes when you get too many notifications at once."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Turn off"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Unlock to see older notifications"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"This device is managed by your parent"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporarily connected"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Poor connection"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Great work!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"To go back, swipe left or right using 3 fingers anywhere on the touchpad."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad showing 3 fingers moving right and left"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Device screen showing animation for back gesture"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Home controls"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Quickly access your home controls as a screensaver"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Undo"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"To go back, swipe left or right with three fingers on the touchpad"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"To go home, swipe up with three fingers on the touchpad"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"To view recent apps, swipe up and hold with three fingers on the touchpad"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"To view all your apps, press the action key on your keyboard"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Use your touchpad to go back"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Swipe left or right using three fingers. Tap to learn more gestures."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Use your touchpad to go home"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Swipe up using three fingers. Tap to learn more gestures."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Use your touchpad to view recent apps"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swipe up and hold using three fingers. Tap to learn more gestures."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use your keyboard to view all apps"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Press the action key at any time. Tap to learn more gestures."</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml
index 0658ce5..39dd7c8 100644
--- a/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Off"</item>
<item msgid="4875147066469902392">"On"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Unavailable"</item>
- <item msgid="2004750556637773692">"Off"</item>
- <item msgid="8968530753931637871">"On"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Unavailable"</item>
<item msgid="5044688398303285224">"Off"</item>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 8a582cb..5680cb7 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Performance"</string>
<string name="user_interface" msgid="3712869377953950887">"User Interface"</string>
<string name="thermal" msgid="6758074791325414831">"Thermal"</string>
+ <string name="custom" msgid="3337456985275158299">"Custom"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Custom Trace Settings"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Restore Default"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"One-handed mode"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hearing devices"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Active"</string>
@@ -431,6 +434,9 @@
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"On"</string>
<string name="zen_mode_off" msgid="1736604456618147306">"Off"</string>
+ <string name="zen_mode_set_up" msgid="7457957033034460064">"Set up"</string>
+ <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Manage in settings"</string>
+ <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{No active modes}=1{{mode} is active}other{# modes are active}}"</string>
<string name="zen_priority_introduction" msgid="3159291973383796646">"You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events, and callers you specify. You\'ll still hear anything you choose to play including music, videos, and games."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"You won\'t be disturbed by sounds and vibrations, except from alarms. You\'ll still hear anything you choose to play including music, videos, and games."</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"Customize"</string>
@@ -469,6 +475,7 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <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> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets on lock screen"</string>
+ <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget added to lock screen"</string>
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Customize"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dismiss"</string>
@@ -1221,7 +1228,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporarily connected"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Poor connection"</string>
@@ -1375,7 +1381,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Great job!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"To go back, swipe left or right using three fingers anywhere on the touchpad."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad showing three fingers moving right and left"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Device screen showing animation for back gesture"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml
index 0658ce5..39dd7c8 100644
--- a/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Off"</item>
<item msgid="4875147066469902392">"On"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Unavailable"</item>
- <item msgid="2004750556637773692">"Off"</item>
- <item msgid="8968530753931637871">"On"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Unavailable"</item>
<item msgid="5044688398303285224">"Off"</item>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 23c3ff3..f2ba704 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Performance"</string>
<string name="user_interface" msgid="3712869377953950887">"User interface"</string>
<string name="thermal" msgid="6758074791325414831">"Thermal"</string>
+ <string name="custom" msgid="3337456985275158299">"Custom"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Custom trace settings"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Restore default"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"One-handed mode"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hearing devices"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Active"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Priority modes"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Done"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"On"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Off"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events and callers you specify. You\'ll still hear anything you choose to play including music, videos and games."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"You won\'t be disturbed by sounds and vibrations, except from alarms. You\'ll still hear anything you choose to play including music, videos and games."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <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> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets on lock screen"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Customise"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dismiss"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"place selected widget"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Lock screen widgets"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Anyone can view widgets on your lock screen, even if your tablet\'s locked."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"unselect widget"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Lock screen widgets"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"To open an app using a widget, you\'ll need to verify that it\'s you. Also, bear in mind that anyone can view them, even when your tablet\'s locked. Some widgets may not have been intended for your lock screen and may be unsafe to add here."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Got it"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Start now"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"No notifications"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"No new notifications"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Notification cooldown is on"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Your device volume and alerts are reduced automatically for up to 2 minutes when you get too many notifications at once."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Turn off"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Unlock to see older notifications"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"This device is managed by your parent"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporarily connected"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Poor connection"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Great work!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"To go back, swipe left or right using 3 fingers anywhere on the touchpad."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad showing 3 fingers moving right and left"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Device screen showing animation for back gesture"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Home controls"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Quickly access your home controls as a screensaver"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Undo"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"To go back, swipe left or right with three fingers on the touchpad"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"To go home, swipe up with three fingers on the touchpad"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"To view recent apps, swipe up and hold with three fingers on the touchpad"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"To view all your apps, press the action key on your keyboard"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Use your touchpad to go back"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Swipe left or right using three fingers. Tap to learn more gestures."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Use your touchpad to go home"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Swipe up using three fingers. Tap to learn more gestures."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Use your touchpad to view recent apps"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swipe up and hold using three fingers. Tap to learn more gestures."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use your keyboard to view all apps"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Press the action key at any time. Tap to learn more gestures."</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml
index 0658ce5..39dd7c8 100644
--- a/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Off"</item>
<item msgid="4875147066469902392">"On"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Unavailable"</item>
- <item msgid="2004750556637773692">"Off"</item>
- <item msgid="8968530753931637871">"On"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Unavailable"</item>
<item msgid="5044688398303285224">"Off"</item>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 23c3ff3..f2ba704 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Performance"</string>
<string name="user_interface" msgid="3712869377953950887">"User interface"</string>
<string name="thermal" msgid="6758074791325414831">"Thermal"</string>
+ <string name="custom" msgid="3337456985275158299">"Custom"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Custom trace settings"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Restore default"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"One-handed mode"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hearing devices"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Active"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Priority modes"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Done"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"On"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Off"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events and callers you specify. You\'ll still hear anything you choose to play including music, videos and games."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"You won\'t be disturbed by sounds and vibrations, except from alarms. You\'ll still hear anything you choose to play including music, videos and games."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <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> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets on lock screen"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Customise"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dismiss"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"place selected widget"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Lock screen widgets"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Anyone can view widgets on your lock screen, even if your tablet\'s locked."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"unselect widget"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Lock screen widgets"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"To open an app using a widget, you\'ll need to verify that it\'s you. Also, bear in mind that anyone can view them, even when your tablet\'s locked. Some widgets may not have been intended for your lock screen and may be unsafe to add here."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Got it"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Start now"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"No notifications"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"No new notifications"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Notification cooldown is on"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Your device volume and alerts are reduced automatically for up to 2 minutes when you get too many notifications at once."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Turn off"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Unlock to see older notifications"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"This device is managed by your parent"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporarily connected"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Poor connection"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Great work!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"To go back, swipe left or right using 3 fingers anywhere on the touchpad."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad showing 3 fingers moving right and left"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Device screen showing animation for back gesture"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Home controls"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Quickly access your home controls as a screensaver"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Undo"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"To go back, swipe left or right with three fingers on the touchpad"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"To go home, swipe up with three fingers on the touchpad"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"To view recent apps, swipe up and hold with three fingers on the touchpad"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"To view all your apps, press the action key on your keyboard"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Use your touchpad to go back"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Swipe left or right using three fingers. Tap to learn more gestures."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Use your touchpad to go home"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Swipe up using three fingers. Tap to learn more gestures."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Use your touchpad to view recent apps"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swipe up and hold using three fingers. Tap to learn more gestures."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use your keyboard to view all apps"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Press the action key at any time. Tap to learn more gestures."</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml
index 0658ce5..39dd7c8 100644
--- a/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Off"</item>
<item msgid="4875147066469902392">"On"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Unavailable"</item>
- <item msgid="2004750556637773692">"Off"</item>
- <item msgid="8968530753931637871">"On"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Unavailable"</item>
<item msgid="5044688398303285224">"Off"</item>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 7ff7900..f99ab9e 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Performance"</string>
<string name="user_interface" msgid="3712869377953950887">"User Interface"</string>
<string name="thermal" msgid="6758074791325414831">"Thermal"</string>
+ <string name="custom" msgid="3337456985275158299">"Custom"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Custom Trace Settings"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Restore Default"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"One-handed mode"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hearing devices"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Active"</string>
@@ -431,6 +434,9 @@
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"On"</string>
<string name="zen_mode_off" msgid="1736604456618147306">"Off"</string>
+ <string name="zen_mode_set_up" msgid="7457957033034460064">"Set up"</string>
+ <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Manage in settings"</string>
+ <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{No active modes}=1{{mode} is active}other{# modes are active}}"</string>
<string name="zen_priority_introduction" msgid="3159291973383796646">"You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events, and callers you specify. You\'ll still hear anything you choose to play including music, videos, and games."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"You won\'t be disturbed by sounds and vibrations, except from alarms. You\'ll still hear anything you choose to play including music, videos, and games."</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"Customize"</string>
@@ -469,6 +475,7 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <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> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets on lock screen"</string>
+ <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget added to lock screen"</string>
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Customize"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dismiss"</string>
@@ -1221,7 +1228,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporarily connected"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Poor connection"</string>
@@ -1375,7 +1381,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Great job!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"To go back, swipe left or right using three fingers anywhere on the touchpad."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad showing three fingers moving right and left"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Device screen showing animation for back gesture"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml
index a6a5fdd..35ab88b 100644
--- a/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Off"</item>
<item msgid="4875147066469902392">"On"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Unavailable"</item>
- <item msgid="2004750556637773692">"Off"</item>
- <item msgid="8968530753931637871">"On"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Unavailable"</item>
<item msgid="5044688398303285224">"Off"</item>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index fcfd1f4..31344fa 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -129,7 +129,7 @@
<string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"¿Quieres detener la grabación?"</string>
<string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"Actualmente, estás grabando toda la pantalla"</string>
<string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Actualmente, estás grabando <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Detener la grabación"</string>
+ <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Detener grabación"</string>
<string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"Compartiendo pantalla"</string>
<string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"¿Quieres dejar de compartir la pantalla?"</string>
<string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Actualmente, estás compartiendo toda la pantalla con <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string>
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Rendimiento"</string>
<string name="user_interface" msgid="3712869377953950887">"Interfaz de usuario"</string>
<string name="thermal" msgid="6758074791325414831">"Térmico"</string>
+ <string name="custom" msgid="3337456985275158299">"Personalizado"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Configuración de rastreo personalizada"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Restablecer configuración predeterminada"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo una mano"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Dispositivos auditivos"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Activos"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modos de prioridad"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Listo"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configuración"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Activado"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Desactivado"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"No te molestarán los sonidos ni las vibraciones, excepto las alarmas, los recordatorios, los eventos y las llamadas de los emisores que especifiques. Podrás escuchar el contenido que reproduzcas, como música, videos y juegos."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"No te molestarán los sonidos ni las vibraciones, excepto las alarmas. Podrás escuchar el contenido que reproduzcas, como música, videos y juegos."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando lento • Se completará en <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> • Cargando • Se completará en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets en la pantalla de bloqueo"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Desliza el dedo a la izquierda para iniciar el instructivo comunal"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Descartar"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"colocar widget seleccionado"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgets en la pantalla de bloqueo"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Los widgets de la pantalla de bloqueo podrán verse incluso si bloqueas la tablet."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"anular la selección del widget"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets en la pantalla de bloqueo"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Para abrir una app usando un widget, debes verificar tu identidad. Además, ten en cuenta que cualquier persona podrá verlo, incluso cuando la tablet esté bloqueada. Es posible que algunos widgets no se hayan diseñados para la pantalla de bloqueo y podría ser peligroso agregarlos allí."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Entendido"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Comenzar ahora"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"No hay notificaciones"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"No hay notificaciones nuevas"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Reducción de sonido de notificaciones activada"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"El volumen y las alertas se reducen por hasta 2 minutos si recibes muchas notificaciones a la vez."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Desactivar"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloquea para ver notificaciones anteriores"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Tu padre o madre administra este dispositivo"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Se requiere de una autenticación. Toca el sensor de huellas dactilares para autenticarte."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Llamada en curso"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móviles"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Conexión establecida"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectado temporalmente"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexión deficiente"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Listo"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"¡Bien hecho!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Atrás"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Para volver, desliza tres dedos hacia la derecha o izquierda en cualquier lugar del panel táctil."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Panel táctil en el que aparecen tres dedos que se mueven hacia la derecha y la izquierda"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Pantalla de un dispositivo en la que aparece una animación del gesto atrás"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroiluminación del teclado"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Controles de la casa"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Usa rápidamente los controles de la casa como protector de pantalla"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Deshacer"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Para ir hacia atrás, desliza hacia la izquierda o la derecha con tres dedos en el panel táctil"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Para ir a la pantalla principal, desliza hacia arriba con tres dedos en el panel táctil"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Para ver las apps recientes, desliza hacia arriba con tres dedos y mantén presionado el panel táctil"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Para ver todas las apps, presiona la tecla de acción en el teclado"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Usa el panel táctil para ir hacia atrás"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Desliza hacia la izquierda o la derecha con tres dedos. Presiona para aprender más gestos."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Usa el panel táctil para ir a la pantalla principal"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Desliza hacia arriba con tres dedos. Presiona para aprender más gestos."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Usa el panel táctil para ver las apps recientes"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Desliza hacia arriba con tres dedos y mantenlos presionados. Presiona para aprender más gestos."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Usa el teclado para ver todas las apps"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Presiona la tecla de acción en cualquier momento. Presiona para aprender más gestos."</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
index 5c1341a..869efff 100644
--- a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Desactivado"</item>
<item msgid="4875147066469902392">"Activado"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"No disponible"</item>
- <item msgid="2004750556637773692">"No"</item>
- <item msgid="8968530753931637871">"Sí"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"No disponible"</item>
<item msgid="5044688398303285224">"Desactivada"</item>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 544939d..3aff0fa 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Rendimiento"</string>
<string name="user_interface" msgid="3712869377953950887">"Interfaz de usuario"</string>
<string name="thermal" msgid="6758074791325414831">"Temperatura"</string>
+ <string name="custom" msgid="3337456985275158299">"Personalizado"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Ajustes de rastreo personalizados"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Restaurar ajustes predeterminados"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo Una mano"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Audífonos"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Activos"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modos prioritarios"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Hecho"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ajustes"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Activado"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Desactivado"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"No te molestarán los sonidos ni las vibraciones, excepto las alarmas, los recordatorios, los eventos y las llamadas que especifiques. Seguirás escuchando el contenido que quieras reproducir, como música, vídeos y juegos."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"No te molestarán los sonidos ni las vibraciones, excepto las alarmas. Seguirás escuchando el contenido que quieras reproducir, como música, vídeos y juegos."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta • En <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> terminará de cargarse"</string>
<string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • Carga completa en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets en la pantalla de bloqueo"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Desliza hacia la izquierda para iniciar el tutorial de la comunidad"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Cerrar"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"colocar widget seleccionado"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgets para la pantalla de bloqueo"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Cualquiera puede ver los widgets de tu pantalla de bloqueo, aunque tu tablet esté bloqueada."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"deseleccionar widget"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets para la pantalla de bloqueo"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Para abrir una aplicación usando un widget, deberás verificar que eres tú. Además, ten en cuenta que cualquier persona podrá verlos, incluso aunque tu tablet esté bloqueada. Es posible que algunos widgets no estén pensados para la pantalla de bloqueo y no sea seguro añadirlos aquí."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Entendido"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Empezar ahora"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"No hay notificaciones"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"No hay notificaciones nuevas"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Bajar el volumen de notificaciones está activado"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"El volumen y las alertas de tu dispositivo se reducen durante hasta 2 minutos si recibes muchas notificaciones a la vez."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Desactivar"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloquea para ver notificaciones anteriores"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo lo gestionan tu padre o tu madre"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticación obligatoria. Toca el sensor de huellas digitales para autenticarte."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Llamada en curso"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móviles"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectada temporalmente"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexión inestable"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Hecho"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"¡Bien hecho!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Atrás"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Para volver, desliza tres dedos hacia la izquierda o la derecha en cualquier punto del panel táctil."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Panel táctil con tres dedos moviéndose hacia la derecha y la izquierda"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Pantalla del dispositivo que muestra una animación del gesto para volver atrás"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroiluminación del teclado"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Controles de la casa"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Usa los controles de tu casa como salvapantallas"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Deshacer"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Para volver atrás, desliza hacia la izquierda o la derecha con tres dedos en el panel táctil"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Para ir a la pantalla de inicio, desliza hacia arriba con tres dedos en el panel táctil"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Para ver las aplicaciones recientes, desliza hacia arriba y mantén pulsado el panel táctil con tres dedos"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Para ver todas tus aplicaciones, pulsa la tecla de acción de tu teclado"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Usa el panel táctil para volver atrás"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Desliza hacia la izquierda o hacia la derecha con tres dedos. Toca para aprender a usar más gestos."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Usa el panel táctil para ir a la pantalla de inicio"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Desliza hacia arriba con tres dedos. Toca para aprender a usar más gestos."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Usa el panel táctil para ver las aplicaciones recientes"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Desliza hacia arriba y mantén pulsado con tres dedos. Toca para aprender a usar más gestos."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Usa el teclado para ver todas las aplicaciones"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pulsa la tecla de acción en cualquier momento. Toca para aprender a usar más gestos."</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/tiles_states_strings.xml b/packages/SystemUI/res/values-es/tiles_states_strings.xml
index fa0b40e..08644e1 100644
--- a/packages/SystemUI/res/values-es/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-es/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Desactivado"</item>
<item msgid="4875147066469902392">"Activado"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"No disponible"</item>
- <item msgid="2004750556637773692">"Desactivado"</item>
- <item msgid="8968530753931637871">"Activado"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"No disponible"</item>
<item msgid="5044688398303285224">"Desactivado"</item>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index fa981fa..5b38ff6 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Jõudlus"</string>
<string name="user_interface" msgid="3712869377953950887">"Kasutajaliides"</string>
<string name="thermal" msgid="6758074791325414831">"Soojus"</string>
+ <string name="custom" msgid="3337456985275158299">"Kohandatud"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Kohandatud jälgimise seaded"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Vaikeseadete taastamine"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Ühekäerežiim"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Kuuldeseadmed"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Ühendatud"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioriteetsed režiimid"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Valmis"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Seaded"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Sees"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Väljas"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Helid ja värinad ei sega teid. Kuulete siiski enda määratud äratusi, meeldetuletusi, sündmusi ja helistajaid. Samuti kuulete kõike, mille esitamise ise valite, sh muusika, videod ja mängud."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Helid ja värinad ei sega teid. Kuulete siiski äratusi. Samuti kuulete kõike, mille esitamise ise valite, sh muusika, videod ja mängud."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Aeglane laadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string>
<string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Lukustuskuva vidinad"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Ühise õpetuse käivitamiseks pühkige vasakule"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Kohandage"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Loobuge"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"asetage valitud vidin"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Lukustuskuva vidinad"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Igaüks saab vaadata luk.kuval olevaid vidinaid, isegi kui tahvelarvuti on lukus."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"tühistage vidina valimine"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Lukustuskuva vidinad"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Rakenduse avamiseks vidina abil peate kinnitama, et see olete teie. Samuti pidage meeles, et kõik saavad vidinaid vaadata, isegi kui teie tahvelarvuti on lukus. Mõni vidin ei pruugi olla ette nähtud teie lukustuskuva jaoks ja seda pole turvaline siia lisada."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Selge"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Alusta kohe"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Märguandeid pole"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Uusi märguandeid ei ole"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Märguannete summutamine on sees"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Kui saate korraga liiga palju märguandeid, vähendab seade automaatselt helitugevust ja minimeerib märguanded kuni kaheks minutiks."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Lülita välja"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Vanemate märguannete nägemiseks avage"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Seda seadet haldab sinu vanem"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Vajalik on autentimine. Puudutage autentimiseks sõrmejäljeandurit."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Käimasolev telefonikõne"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiilne andmeside"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Ühendatud"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Ajutiselt ühendatud"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Kehv ühendus"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Valmis"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Väga hea!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Tagasi"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Tagasiliikumiseks pühkige puuteplaadil kolme sõrmega vasakule või paremale."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Puuteplaat kolme paremale ja vasakule liikuva sõrmega"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Seadme ekraanil näidatakse tagasiliigutuse animatsiooni"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klaviatuuri taustavalgustus"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Kodu juhtelemendid"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Juurdepääs kodu juhtelementidele ekraanisäästjalt"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Võta tagasi"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Tagasiliikumiseks pühkige puuteplaadil kolme sõrmega vasakule või paremale"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Avakuvale liikumiseks pühkige puuteplaadil kolme sõrmega üles"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Hiljutiste rakenduste kuvamiseks pühkige puuteplaadil kolme sõrmega üles ja hoidke sõrmi puuteplaadil"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Kõigi oma rakenduste kuvamiseks vajutage klaviatuuril toiminguklahvi"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Puuteplaadi kasutamine tagasiliikumiseks"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Pühkige kolme sõrmega vasakule või paremale. Puudutage žestide kohta lisateabe saamiseks."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Puuteplaadi kasutamine avakuvale liikumiseks"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Pühkige kolme sõrmega üles. Puudutage žestide kohta lisateabe saamiseks."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Puuteplaadi kasutamine hiljutiste rakenduste kuvamiseks"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Pühkige kolme sõrmega üles ja hoidke sõrmi plaadil. Puudutage žestide kohta lisateabe saamiseks."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Klaviatuuri kasutamine kõigi rakenduste kuvamiseks"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Vajutage soovitud ajal toiminguklahvi. Puudutage žestide kohta lisateabe saamiseks."</string>
</resources>
diff --git a/packages/SystemUI/res/values-et/tiles_states_strings.xml b/packages/SystemUI/res/values-et/tiles_states_strings.xml
index 65bf1a9..704649e 100644
--- a/packages/SystemUI/res/values-et/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-et/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Väljas"</item>
<item msgid="4875147066469902392">"Sees"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Pole saadaval"</item>
- <item msgid="2004750556637773692">"Väljas"</item>
- <item msgid="8968530753931637871">"Sees"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Pole saadaval"</item>
<item msgid="5044688398303285224">"Väljas"</item>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 7094969..6471c3b 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Errendimendua"</string>
<string name="user_interface" msgid="3712869377953950887">"Erabiltzaile-interfazea"</string>
<string name="thermal" msgid="6758074791325414831">"Termikoa"</string>
+ <string name="custom" msgid="3337456985275158299">"Pertsonalizatua"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Arrasto pertsonalizatuen ezarpenak"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Leheneratu balio lehenetsia"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Esku bakarreko modua"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Entzumen-gailuak"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktibo"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Lehentasunezko moduak"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Eginda"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ezarpenak"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Aktibatuta"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Desaktibatuta"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Gailuak ez du egingo ez soinurik ez dardararik, baina alarmak, gertaera eta abisuen tonuak, eta aukeratzen dituzun deitzaileen dei-tonuak joko ditu. Bestalde, zuk erreproduzitutako guztia entzungo duzu, besteak beste, musika, bideoak eta jokoak."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Gailuak ez du egingo ez soinurik ez dardararik, baina alarmak joko ditu. Hala ere, zuk erreproduzitutako guztia entzun ahal izango duzu, besteak beste, musika, bideoak eta jokoak."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mantso kargatzen • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte"</string>
<string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Kargatzen • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Pantaila blokeatuko widgetak"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Tutorial komuna hasteko, pasatu hatza ezkerrera"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Pertsonalizatu"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Baztertu"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"kokatu hautatutako widgeta"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Pantaila blokeatuko widgetak"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Edonork ikus ditzake pantaila blokeatuko widgetak, tableta blokeatuta badago ere."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"desautatu widgeta"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Pantaila blokeatuko widgetak"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Aplikazio bat widget baten bidez irekitzeko, zeu zarela egiaztatu beharko duzu. Gainera, kontuan izan edonork ikusi ahalko dituela halako widgetak, tableta blokeatuta badago ere. Baliteke widget batzuk pantaila blokeaturako egokiak ez izatea, eta agian ez da segurua haiek bertan gehitzea."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Ados"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Hasi"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Ez dago jakinarazpenik"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Ez dago jakinarazpen berririk"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Jakinarazpenak arintzeko ezarpena aktibatuta dago"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Aldi berean jakinarazpen gehiegi jasotzen badituzu, gailuaren bolumena eta alertak automatikoki murriztuko dira 2 minutuz (gehienez)."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Desaktibatu"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Jakinarazpen zaharragoak ikusteko, desblokeatu"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Zure gurasoak kudeatzen du gailua"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentifikazioa behar da. Autentifikatzeko, ukitu hatz-marken sentsorea."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefono-dei bat abian da"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Datu-konexioa"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> (<xliff:g id="NETWORKMODE">%2$s</xliff:g>)"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Konektatuta"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Aldi baterako konektatuta"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Konexio ahula"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Eginda"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Bikain!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Egin atzera"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Atzera egiteko, pasatu 3 hatz ezkerrera edo eskuinera ukipen-panelean."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"3 hatz ukipen-panel baten gainean eskuinera eta ezkerrera mugitzen erakusten duen irudia"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Gailuaren pantailan atzera egiteko keinuaren animazioa erakusten duen irudia"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Teklatuaren hondoko argia"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Etxeko gailuen kontrola"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Kontrolatu etxeko gailuak pantaila-babesletik"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Desegin"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Atzera egiteko, pasatu 3 hatz ukipen-panelean ezkerrera edo eskuinera"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Hasierako pantailara joateko, pasatu 3 hatz ukipen-pantailan"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Azkenaldiko aplikazioak ikusteko, pasatu 3 hatz ukipen-panelean gora eta eduki sakatuta"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Aplikazio guztiak ikusteko, sakatu teklatuko ekintza-tekla"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Erabili ukipen-panela atzera egiteko"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Pasatu 3 hatz ezkerrera edo eskuinera. Sakatu keinu gehiago ikasteko."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Erabili ukipen-panela hasierako pantailara joateko"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Pasatu 3 hatz. Sakatu keinu gehiago ikasteko."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Erabili ukipen-panela azkenaldiko aplikazioak ikusteko"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Pasatu 3 hatz gora eta eduki sakatuta. Sakatu keinu gehiago ikasteko."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Erabili teklatua aplikazio guztiak ikusteko"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Sakatu ekintza-tekla edonoiz. Sakatu keinu gehiago ikasteko."</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu/tiles_states_strings.xml b/packages/SystemUI/res/values-eu/tiles_states_strings.xml
index 75162bc..13e14e0 100644
--- a/packages/SystemUI/res/values-eu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-eu/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Desaktibatuta"</item>
<item msgid="4875147066469902392">"Aktibatuta"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Ez dago erabilgarri"</item>
- <item msgid="2004750556637773692">"Desaktibatuta"</item>
- <item msgid="8968530753931637871">"Aktibatuta"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Ez dago erabilgarri"</item>
<item msgid="5044688398303285224">"Desaktibatuta"</item>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 0c09567..f4b9d9e 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"عملکرد"</string>
<string name="user_interface" msgid="3712869377953950887">"میانای کاربر"</string>
<string name="thermal" msgid="6758074791325414831">"حرارتی"</string>
+ <string name="custom" msgid="3337456985275158299">"سفارشی"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"تنظیمات ردیابی سفارشی"</string>
+ <string name="restore_default" msgid="5259420807486239755">"بازیابی پیشفرض"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"حالت یکدستی"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"سمعک"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"فعال"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"حالتهای اولویتدار"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"تمام"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"تنظیمات"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"روشن"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"خاموش"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"بهجز هشدارها، یادآوریها، رویدادها و تماسگیرندگانی که خودتان مشخص میکنید، هیچ صدا و لرزشی نخواهید داشت. همچنان صدای مواردی را که پخش میکنید میشنوید (ازجمله صدای موسیقی، ویدیو و بازی)."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"بهجز هشدارها، هیچ صدا و لرزشی نخواهید داشت. همچنان صدای مواردی را که پخش میکنید میشنوید (ازجمله صدای موسیقی، ویدیو و بازی)."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ کردن آهسته • <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> • درحال شارژ شدن • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ابزارکها در صفحه قفل"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"برای شروع آموزش گامبهگام عمومی، تند بهچپ بکشید"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"سفارشیسازی"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"بستن"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"جایگذاری ابزارک انتخابشده"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"ابزارههای صفحه قفل"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"همه میتوانند ابزارهها را در صفحه قفل شما ببینند، حتی اگر رایانه لوحی قفل باشد."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"لغو انتخاب ابزاره"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ابزارکهای صفحه قفل"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"برای باز کردن برنامه بااستفاده از ابزارک، باید هویت خودتان را بهتأیید برسانید. همچنین، بهخاطر داشته باشید که همه میتوانند آنها را مشاهده کنند، حتی وقتی رایانه لوحیتان قفل است. برخیاز ابزارکها ممکن است برای صفحه قفل درنظر گرفته نشده باشند و ممکن است اضافه کردن آنها در اینجا ناامن باشد."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"متوجهام"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"اکنون شروع کنید"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"اعلانی موجود نیست"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"اعلان جدیدی وجود ندارد"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"«استراحت اعلانها» روشن است"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"وقتی بهطور همزمان تعداد بسیار زیادی اعلان دریافت کنید، میزان صدای دستگاه و هشدارها بهطور خودکار تا ۲ دقیقه کاهش مییابد."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"خاموش کردن"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"برای دیدن اعلانهای قبلی قفل را باز کنید"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"این دستگاه را ولیتان مدیریت میکند"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"اصالتسنجی لازم است. برای اصالتسنجی، حسگر اثر انگشت را لمس کنید."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"تماس تلفنی درحال انجام"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"داده تلفن همراه"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"متصل است"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"موقتاً متصل است"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"اتصال ضعیف"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"تمام"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"عالی است!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"برگشتن"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"برای برگشتن، در هر جایی از صفحه لمسی، با سه انگشت تند بهچپ یا راست بکشید."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"صفحه لمسی که سه انگشت را درحال حرکت بهسمت راست و چپ نشان میدهد"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"صفحهنمایش دستگاه درحال نمایش پویانمایی مربوط به اشاره برگشتن"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"نور پسزمینه صفحهکلید"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"کنترل خانه هوشمند"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"به کنترل خانه هوشمند بهعنوان محافظ صفحهنمایش دسترسی سریع دارید"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"واگرداندن"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"برای برگشتن، در صفحه لمسی با سه انگشت تند بهچپ یا راست بکشید"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"برای رفتن به صفحه اصلی، در صفحه لمسی با سه انگشت تند بهبالا بکشید"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"برای مشاهده برنامههای اخیر، در صفحه لمسی با سه انگشت تند بهبالا بکشید و نگه دارید"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"برای مشاهده همه برنامهها، دکمه کنش در صفحهکلید را فشار دهید"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"برای برگشتن از صفحه لمسی استفاده کنید"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"با سه انگشت تند بهچپ یا راست بکشید. برای آشنایی با اشارههای بیشتر، تکضرب بزنید."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"برای رفتن به صفحه اصلی از صفحه لمسی استفاده کنید"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"با سه انگشت تند بهبالا بکشید. برای آشنایی با اشارههای بیشتر، تکضرب بزنید."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"برای مشاهده برنامههای اخیر از صفحه لمسی استفاده کنید"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"با سه انگشت تند بهبالا بکشید و نگه دارید. برای آشنایی با اشارههای بیشتر، تکضرب بزنید."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"برای مشاهده همه برنامهها، از صفحهکلید استفاده کنید"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"در هرزمانی دکمه کنش را فشار دهید. برای آشنایی با اشارههای بیشتر، تکضرب بزنید."</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/tiles_states_strings.xml b/packages/SystemUI/res/values-fa/tiles_states_strings.xml
index b2444e8..756b442 100644
--- a/packages/SystemUI/res/values-fa/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fa/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"خاموش"</item>
<item msgid="4875147066469902392">"روشن"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"دردسترس نیست"</item>
- <item msgid="2004750556637773692">"خاموش"</item>
- <item msgid="8968530753931637871">"روشن"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"دردسترس نیست"</item>
<item msgid="5044688398303285224">"خاموش"</item>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 10a2dff..79962f0 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Suorituskyky"</string>
<string name="user_interface" msgid="3712869377953950887">"Käyttöliittymä"</string>
<string name="thermal" msgid="6758074791325414831">"Lämpökamera"</string>
+ <string name="custom" msgid="3337456985275158299">"Yksilöity"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Yksilöidyt jäljittämisasetukset"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Palauta oletus"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Yhden käden moodi"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Kuulolaitteet"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktiivinen"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioriteettitilat"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Valmis"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Asetukset"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Päällä"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Pois päältä"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Äänet ja värinät eivät häiritse sinua, paitsi jos ne ovat hälytyksiä, muistutuksia, tapahtumia tai määrittämiäsi soittajia. Kuulet edelleen kaiken valitsemasi sisällön, kuten musiikin, videot ja pelit."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Äänet ja värinät eivät häiritse sinua, paitsi jos ne ovat hälytyksiä. Kuulet edelleen kaiken valitsemasi sisällön, kuten musiikin, videot ja pelit."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu hitaasti • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string>
<string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgetit lukitusnäytöllä"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Aloita yhteisöesittely pyyhkäisemällä vasemmalle"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Muokkaa"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Hylkää"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"aseta valittu widget"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Lukitusnäytön widgetit"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Kaikki voivat nähdä widgetit lukitusnäytöllä, vaikka tabletti olisi lukittuna."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"poista widgetin valinta"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Lukitusnäytön widgetit"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Jos haluat avata sovelluksen käyttämällä widgetiä, sinun täytyy vahvistaa henkilöllisyytesi. Muista myös, että widgetit näkyvät kaikille, vaikka tabletti olisi lukittuna. Jotkin widgetit on ehkä tarkoitettu lukitusnäytölle, ja niiden lisääminen tänne ei välttämättä ole turvallista."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Selvä"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Aloita nyt"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Ei ilmoituksia"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Ei uusia ilmoituksia"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Ilmoitusten vaimennus on päällä"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Äänenvoimakkuus ja ilmoitukset vaimennetaan enintään 2 minuutiksi, kun saat paljon ilmoituksia."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Laita pois päältä"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Avaa lukitus niin näet ilmoituksia"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Vanhempasi ylläpitää tätä laitetta"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Todennus vaaditaan. Todenna koskettamalla sormenjälkitunnistinta."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Puhelu käynnissä"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiilidata"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Yhdistetty"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Väliaikaisesti yhdistetty"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Heikko yhteys"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Valmis"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Hienoa!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Takaisin"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Jos haluat siirtyä takaisin, pyyhkäise kosketuslevyllä vasemmalle tai oikealle kolmella sormella."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Kosketuslevy, jolla kolme sormea liikkuu oikealle ja vasemmalle"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Laitteen näyttö, jolla näkyy animaatio takaisin-eleestä"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Näppämistön taustavalo"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Kodin ohjaus"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Avaa kodin ohjaus nopeasti näytönsäästäjän kautta"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Kumoa"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Jos haluat siirtyä takaisin, pyyhkäise kosketuslevyllä vasemmalle tai oikealle kolmella sormella."</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Jos haluat siirtyä aloitussivulle, pyyhkäise kosketuslevyllä ylös kolmella sormella"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Näet äskeiset sovellukset, kun pyyhkäiset ylös ja pidät kosketuslevyä painettuna kolmella sormella."</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Jos haluat nähdä kaikki sovellukset, paina näppäimistön toimintonäppäintä"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Takaisin siirtyminen kosketuslevyn avulla"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Pyyhkäise vasemmalle tai oikealle kolmella sormella. Lue lisää eleistä napauttamalla."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Aloitusnäytölle siirtyminen kosketuslevyn avulla"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Pyyhkäise ylös kolmella sormella. Lue lisää eleistä napauttamalla."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Äskettäin käytettyjen sovellusten näkeminen kosketuslevyn avulla"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Pyyhkäise ylös ja pidä kosketuslevyä painettuna kolmella sormella. Lue lisää eleistä napauttamalla."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Kaikkien sovellusten näkeminen näppäimistön avulla"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Voit painaa toimintonäppäintä milloin tahansa. Lue lisää eleistä napauttamalla."</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/tiles_states_strings.xml b/packages/SystemUI/res/values-fi/tiles_states_strings.xml
index a7a6bdc..5ecc9595 100644
--- a/packages/SystemUI/res/values-fi/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fi/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Poissa päältä"</item>
<item msgid="4875147066469902392">"Päällä"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Ei saatavilla"</item>
- <item msgid="2004750556637773692">"Pois päältä"</item>
- <item msgid="8968530753931637871">"Päällä"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Ei saatavilla"</item>
<item msgid="5044688398303285224">"Poissa päältä"</item>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index b8c30ee..f34ce98 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -138,7 +138,7 @@
<string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"Vous partagez actuellement une appli"</string>
<string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"Arrêter le partage"</string>
<string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"Diffusion de l\'écran en cours…"</string>
- <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Arrêter de diffuser?"</string>
+ <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Arrêter la diffusion?"</string>
<string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Vous diffusez actuellement l\'intégralité de votre écran sur <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Vous diffusez actuellement l\'intégralité de votre écran sur un appareil à proximité"</string>
<string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Vous diffusez actuellement <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> sur <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Performance"</string>
<string name="user_interface" msgid="3712869377953950887">"Interface utilisateur"</string>
<string name="thermal" msgid="6758074791325414831">"Thermique"</string>
+ <string name="custom" msgid="3337456985275158299">"Personnalisé"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Paramètres personnalisés de la trace"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Restaurer la valeur par défaut"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Mode Une main"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Appareils auditifs"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Actives"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modes prioritaires"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"OK"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Paramètres"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Activé"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Désactivé"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Vous ne serez pas dérangé par les sons et les vibrations, sauf pour les alarmes, les rappels, les événements et les appelants que vous sélectionnez. Vous entendrez tout ce que vous choisissez d\'écouter, y compris la musique, les vidéos et les jeux."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangé par les sons et les vibrations, sauf pour les alarmes. Vous entendrez tout ce que vous choisissez d\'écouter, y compris la musique, les vidéos et les jeux."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"En recharge lente : <xliff:g id="PERCENTAGE">%2$s</xliff:g> • Terminée <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> • Recharge en cours… • Se terminera dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets sur l\'écran de verrouillage"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Balayer l\'écran vers la gauche pour démarrer le tutoriel communautaire"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personnaliser"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Fermer"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"placer le widget sélectionné"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgets de l\'écran de verrouillage"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"N\'importe qui peut voir les widgets sur votre écran de verrouillage, même si votre tablette est verrouillée."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"désélectionner le widget"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets de l\'écran de verrouillage"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Pour ouvrir une appli à l\'aide d\'un widget, vous devrez confirmer votre identité. En outre, gardez à l\'esprit que tout le monde peut les voir, même lorsque votre tablette est verrouillée. Certains widgets n\'ont peut-être pas été conçus pour votre écran de verrouillage et il pourrait être dangereux de les ajouter ici."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Commencer"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Aucune notification"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Aucune nouvelle notification"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"L\'atténuation des notifications est activée"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Le volume de votre appareil est réduit pendant deux minutes si vous recevez trop de notifications."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Désactiver"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Déverr. pour voir les anciennes notif."</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Cet appareil est géré par ton parent"</string>
@@ -1006,7 +1012,7 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"enregistrement d\'écran"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sans titre"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Veille"</string>
- <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Taille de police"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Taille de la police"</string>
<string name="font_scaling_smaller" msgid="1012032217622008232">"Rapetisser"</string>
<string name="font_scaling_larger" msgid="5476242157436806760">"Agrandir"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Fenêtre d\'agrandissement"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentification requise. Touchez le capteur d\'empreintes digitales pour vous authentifier."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Appel téléphonique en cours…"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Données cellulaires"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Connexion active"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connectée temporairement"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Connexion faible"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"OK"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Bon travail!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Retour"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Pour revenir en arrière, balayez vers la gauche ou la droite en utilisant trois doigts n\'importe où sur le pavé tactile."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Pavé tactile montrant trois doigts se déplaçant à droite et à gauche"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Écran de l\'appareil montrant l\'animation pour le geste de retour"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Rétroéclairage du clavier"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Domotique"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Accès rapide : domotique sous forme d\'Écran de veille"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Annuler"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Pour revenir en arrière, balayez l\'écran vers la gauche ou vers la droite avec trois doigts sur le pavé tactile"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Pour accéder à l\'écran d\'accueil, balayez l\'écran vers le haut avec trois doigts sur le pavé tactile"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Pour afficher les applis récentes, balayez l\'écran vers le haut avec trois doigts sur le pavé tactile et maintenez-les en place"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Pour afficher toutes vos applis, appuyez sur la touche d\'action de votre clavier"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Utiliser votre pavé tactile pour revenir en arrière"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Balayez vers la gauche ou vers la droite avec trois doigts. Touchez pour apprendre d\'autres gestes."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Utilisez votre pavé tactile pour accéder à l\'écran d\'accueil"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Balayez l\'écran vers le haut avec trois doigts. Touchez pour apprendre d\'autres gestes."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Utiliser le pavé tactile pour afficher les applis récentes"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Balayez l\'écran vers le haut avec trois doigts et maintenez-les en place. Touchez pour apprendre d\'autres gestes."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Utiliser votre clavier pour afficher toutes les applis"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Appuyez sur la touche d\'action à tout moment. Touchez pour apprendre d\'autres gestes."</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
index 75be453..f12634f 100644
--- a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Désactivée"</item>
<item msgid="4875147066469902392">"Activé"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Non accessible"</item>
- <item msgid="2004750556637773692">"Désactivé"</item>
- <item msgid="8968530753931637871">"Activé"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Non disponible"</item>
<item msgid="5044688398303285224">"Désactivée"</item>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 6fc4732..ad63e9e 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -145,7 +145,7 @@
<string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"Vous castez actuellement <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> sur un appareil à proximité"</string>
<string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"Vous castez actuellement du contenu sur <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"Vous castez actuellement du contenu sur un appareil à proximité"</string>
- <string name="cast_to_other_device_stop_dialog_button" msgid="6420183747435521834">"Arrêter de caster du contenu"</string>
+ <string name="cast_to_other_device_stop_dialog_button" msgid="6420183747435521834">"Arrêter de caster"</string>
<string name="close_dialog_button" msgid="4749497706540104133">"Fermer"</string>
<string name="issuerecord_title" msgid="286627115110121849">"Enregistreur de problèmes"</string>
<string name="issuerecord_background_processing_label" msgid="1666840264959336876">"Enregistrement du problème"</string>
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Performances"</string>
<string name="user_interface" msgid="3712869377953950887">"Interface utilisateur"</string>
<string name="thermal" msgid="6758074791325414831">"Thermique"</string>
+ <string name="custom" msgid="3337456985275158299">"Personnalisé"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Paramètres Trace personnalisés"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Rétablir les paramètres par défaut"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Mode une main"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Appareils auditifs"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Actifs"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modes prioritaires"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"OK"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Paramètres"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Activé"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Désactivé"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Vous ne serez pas dérangé par des sons ou des vibrations, hormis ceux des alarmes, des rappels, des événements et des appelants de votre choix. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangé par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, comme la musique, les vidéos et les jeux."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge lente • Temps restant : <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> • Recharge • Temps restant : <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets sur l\'écran de verrouillage"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Balayer vers la gauche pour démarrer le tutoriel collectif"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personnaliser"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Fermer"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"positionner le widget sélectionné"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgets sur l\'écran de verrouillage"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"N\'importe qui peut consulter les widgets sur votre écran de verrouillage, même si votre tablette est verrouillée."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"désélectionner le widget"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets pour l\'écran de verrouillage"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Pour ouvrir une appli à l\'aide d\'un widget, vous devez confirmer qu\'il s\'agit bien de vous. N\'oubliez pas non plus que tout le monde peut voir vos widgets, même lorsque votre tablette est verrouillée. Certains d\'entre eux n\'ont pas été conçus pour l\'écran de verrouillage et les ajouter à cet endroit peut s\'avérer dangereux."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Commencer"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Aucune notification"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Aucune nouvelle notification"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"La limitation des notifications est activée"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Les alertes et le volume de l\'appareil sont réduits automatiquement pendant 2 minutes max. quand vous recevez trop de notifications à la fois."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Désactiver"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Déverrouiller pour voir anciennes notifications"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Cet appareil est géré par tes parents"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentification requise. Appuyez sur le lecteur d\'empreintes digitales pour vous authentifier."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Appel téléphonique en cours"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Données mobiles"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Connecté"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connexion temporaire"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Connexion médiocre"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"OK"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Bravo !"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Retour"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Pour retourner en arrière, balayez vers la gauche avec trois doigts n\'importe où sur le pavé tactile."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Pavé tactile sur lequel trois doigts glissent vers la droite, puis vers la gauche"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Écran d\'un appareil affichant l\'animation du geste Retour"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Rétroéclairage du clavier"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Contrôle de la maison"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Domotique sous forme d\'économiseur d\'écran"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Annuler"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Pour retourner en arrière, glissez vers la gauche ou la droite avec trois doigts sur le pavé tactile"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Pour revenir à l\'accueil, balayez vers le haut avec trois doigts sur le pavé tactile"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Pour afficher les applis récentes, balayez vers le haut avec trois doigts sur le pavé tactile et maintenez-les."</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Pour afficher toutes vos applis, appuyez sur la touche d\'action de votre clavier"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Utilisez votre pavé tactile pour revenir en arrière"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Balayez vers la gauche ou la droite en utilisant trois doigts. Appuyez pour apprendre d\'autres gestes."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Utilisez votre pavé tactile pour revenir à l\'accueil"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Balayez vers le haut avec trois doigts. Appuyez pour apprendre d\'autres gestes."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Utilisez votre pavé tactile pour afficher les applis récentes"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Balayez vers le haut en utilisant trois doigts et maintenez. Appuyez pour apprendre d\'autres gestes."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Utilisez votre clavier pour afficher toutes les applis"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Appuyez sur la touche d\'action à tout moment. Appuyez pour apprendre d\'autres gestes."</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr/tiles_states_strings.xml b/packages/SystemUI/res/values-fr/tiles_states_strings.xml
index daa9152..fcdd9f0 100644
--- a/packages/SystemUI/res/values-fr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fr/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Désactivé"</item>
<item msgid="4875147066469902392">"Activé"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Non disponible"</item>
- <item msgid="2004750556637773692">"Désactivé"</item>
- <item msgid="8968530753931637871">"Activé"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Indisponible"</item>
<item msgid="5044688398303285224">"Désactivé"</item>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 7b39df7..913e589 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Rendemento"</string>
<string name="user_interface" msgid="3712869377953950887">"Interface de usuario"</string>
<string name="thermal" msgid="6758074791325414831">"Térmico"</string>
+ <string name="custom" msgid="3337456985275158299">"Personalizada"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Configuración de rastrexo personalizada"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Restaurar configuración predeterminada"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo dunha soa man"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Dispositivos auditivos"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Activos"</string>
@@ -431,6 +434,12 @@
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configuración"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Activado"</string>
<string name="zen_mode_off" msgid="1736604456618147306">"Desactivado"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
+ <skip />
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
+ <skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Non te molestará ningún son nin vibración, agás os procedentes de alarmas, recordatorios, eventos e os emisores de chamada especificados. Seguirás escoitando todo aquilo que decidas reproducir, mesmo a música, os vídeos e os xogos."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Non te molestará ningún son nin vibración, agás os procedentes de alarmas. Seguirás escoitando todo aquilo que decidas reproducir, mesmo a música, os vídeos e os xogos."</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"Personalizar"</string>
@@ -469,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando lentamente • A carga completarase en <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> • Cargando • A carga completarase en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets na pantalla de bloqueo"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Pasa o dedo cara á esquerda para iniciar o titorial comunitario"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Pechar"</string>
@@ -554,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Iniciar agora"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Non hai notificacións"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Non hai notificacións novas"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"A opción Amainar notificacións está activada"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Cando recibas moitas notificacións, o volume e as alertas reduciranse automaticamente durante ata dous minutos."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Desactivar"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloquea para ver máis notificacións"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"O teu pai ou nai xestiona este dispositivo"</string>
@@ -1223,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Requírese autenticación. Para autenticarte, toca o sensor de impresión dixital."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada telefónica en curso"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móbiles"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Conectada"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectada temporalmente"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexión deficiente"</string>
@@ -1377,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Feito"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Moi ben!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Volver"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Para volver, pasa tres dedos cara á esquerda ou cara á dereita en calquera lugar do panel táctil."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Panel táctil que mostra tres dedos movéndose á dereita e á esquerda"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Pantalla do dispositivo que mostra unha animación do xesto de retroceso"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroiluminación do teclado"</string>
diff --git a/packages/SystemUI/res/values-gl/tiles_states_strings.xml b/packages/SystemUI/res/values-gl/tiles_states_strings.xml
index 8e3fb26..03b934e 100644
--- a/packages/SystemUI/res/values-gl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-gl/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Non"</item>
<item msgid="4875147066469902392">"Si"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Non dispoñible"</item>
- <item msgid="2004750556637773692">"Desactivado"</item>
- <item msgid="8968530753931637871">"Activado"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Non dispoñible"</item>
<item msgid="5044688398303285224">"Non"</item>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 78e86fa..8fd8b3e 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"પર્ફોર્મન્સ"</string>
<string name="user_interface" msgid="3712869377953950887">"યૂઝર ઇન્ટરફેસ"</string>
<string name="thermal" msgid="6758074791325414831">"થર્મલ"</string>
+ <string name="custom" msgid="3337456985275158299">"કસ્ટમ"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"કસ્ટમ ટ્રેસ સેટિંગ"</string>
+ <string name="restore_default" msgid="5259420807486239755">"ડિફૉલ્ટ રિસ્ટોર કરો"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"એક-હાથે વાપરો મોડ"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"સાંભળવામાં મદદ આપતા ડિવાઇસ"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"સક્રિય"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"પ્રાધાન્યતાના મોડ"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"થઈ ગયું"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"સેટિંગ"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"ચાલુ"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"બંધ"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"અલાર્મ, રિમાઇન્ડર, ઇવેન્ટ અને તમે ઉલ્લેખ કરો તે કૉલર સિવાય તમને ધ્વનિ કે વાઇબ્રેશન દ્વારા ખલેલ પહોંચાડવામાં આવશે નહીં. સંગીત, વીડિઓ અને રમતો સહિત તમે જે કંઈપણ ચલાવવાનું પસંદ કરશો તે સંભળાતું રહેશે."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"અલાર્મ સિવાય તમને ધ્વનિ કે વાઇબ્રેશન દ્વારા ખલેલ પહોંચાડવામાં આવશે નહીં. સંગીત, વીડિઓ અને રમતો સહિત તમે જે કંઈપણ ચલાવવાનું પસંદ કરશો તે સંભળાતું રહેશે."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ધીમેથી ચાર્જ થઈ રહ્યું છે • <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> • ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં પૂરું ચાર્જ થઈ જશે"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"લૉક સ્ક્રીન પર વિજેટ"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"કૉમ્યુનલ ટ્યૂટૉરિઅલ શરૂ કરવા માટે ડાબે સ્વાઇપ કરો"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"કસ્ટમાઇઝ કરો"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"છોડી દો"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"પસંદ કરેલું વિજેટ મૂકો"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"લૉક સ્ક્રીન વિજેટ"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"તમારું ટૅબ્લેટ લૉક કરેલું હોય તો પણ કોઈપણ તમારી લૉક સ્ક્રીન પર વિજેટ જોઈ શકે છે."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"વિજેટ નાપસંદ કરો"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"લૉક સ્ક્રીન વિજેટ"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"વિજેટનો ઉપયોગ કરીને ઍપ ખોલવા માટે, તમારે એ ચકાસણી કરવાની જરૂર રહેશે કે આ તમે જ છો. તે ઉપરાંત, ધ્યાનમાં રાખો કે તમારું ટૅબ્લેટ લૉક કરેલું હોય તો પણ કોઈપણ વ્યક્તિ તેમને જોઈ શકે છે. અમુક વિજેટ કદાચ તમારી લૉક સ્ક્રીન માટે બનાવવામાં આવ્યા ન હોઈ શકે છે અને તેમને અહીં ઉમેરવાનું અસલામત હોઈ શકે છે."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"સમજાઈ ગયું"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"હવે શરૂ કરો"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"કોઈ નોટિફિકેશન નથી"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"કોઈ નવું નોટિફિકેશન નથી"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"નોટિફિકેશન કૂલડાઉન ચાલુ છે"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"જ્યારે તમને એકસાથે ઘણા બધા નોટિફિકેશન મળે ત્યારે તમારા ડિવાઇસનું વૉલ્યૂમ અને અલર્ટ ઑટોમૅટિક રીતે 2 મિનિટ જેટલા સમય માટે ઘટાડવામાં આવે છે."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"બંધ કરો"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"જૂના નોટિફિકેશન જોવા માટે અનલૉક કરો"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"આ ડિવાઇસ તમારા માતાપિતા દ્વારા મેનેજ કરવામાં આવે છે"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"પ્રમાણીકરણ આવશ્યક છે. પ્રમાણિત કરવા માટે ફિંગરપ્રિન્ટ સેન્સરને ટચ કરો."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ફોન કૉલ ચાલુ છે"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"મોબાઇલ ડેટા"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"કનેક્ટ કરેલું"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"હંગામી રીતે કનેક્ટ કર્યું"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"નબળું કનેક્શન"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"થઈ ગયું"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ખૂબ સરસ કામ!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"પાછા જાઓ"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"પાછા જવા માટે, ત્રણ આંગળીઓનો ઉપયોગ કરીને ટચપૅડ પર કોઈપણ જગ્યાએ ડાબે કે જમણે સ્વાઇપ કરો."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"જમણી અને ડાબી તરફ ખસી રહેલી ત્રણ આંગળીઓ બતાવતું ટચપૅડ"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"પાછા જવા માટેના સંકેત માટેનું ઍનિમેશન બતાવતી ડિવાઇસ સ્ક્રીન"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"કીબોર્ડની બૅકલાઇટ"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"ઘરેલું સાધનોના નિયંત્રણો"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"સ્ક્રીનસેવર તરીકે તમારા ઘરેલું સાધનોના નિયંત્રણો ઝડપથી ઍક્સેસ કરો"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"છેલ્લો ફેરફાર રદ કરો"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"પાછા જવા માટે, ટચપૅડ પર ત્રણ આંગળી વડે ડાબે અથવા જમણે સ્વાઇપ કરો"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"હોમ સ્ક્રીન પર જવા માટે, ટચપૅડ પર ત્રણ આંગળીઓ વડે ઉપર સ્વાઇપ કરો"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"તાજેતરની ઍપ જોવા માટે, ટચપૅડ પર ત્રણ આંગળીઓ વડે ઉપર સ્વાઇપ કરો અને દબાવી રાખો"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"તમારી બધી ઍપ જોવા માટે, તમારા કીબોર્ડ પર ઍક્શન કી દબાવો"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"પાછા જવા માટે તમારા ટચપૅડનો ઉપયોગ કરો"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"ત્રણ આંગળીનો ઉપયોગ કરીને ડાબે અથવા જમણે સ્વાઇપ કરો. સંકેતો વિશે વધુ જાણવા માટે ટૅપ કરો."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"હોમ સ્ક્રીન પર જવા માટે તમારા ટચપૅડનો ઉપયોગ કરો"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"ત્રણ આંગળીનો ઉપયોગ કરીને ઉપર સ્વાઇપ કરો. સંકેતો વિશે વધુ જાણવા માટે ટૅપ કરો."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"તમારી તાજેતરની ઍપ જોવા માટે તમારા ટચપૅડનો ઉપયોગ કરો"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"ત્રણ આંગળીઓનો ઉપયોગ કરીને ઉપર સ્વાઇપ કરો અને દબાવી રાખો. સંકેતો વિશે વધુ જાણવા માટે ટૅપ કરો."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"બધી ઍપ જોવા માટે તમારા કીબોર્ડનો ઉપયોગ કરો"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"કોઈપણ સમયે ઍક્શન કી દબાવો. સંકેતો વિશે વધુ જાણવા માટે ટૅપ કરો."</string>
</resources>
diff --git a/packages/SystemUI/res/values-gu/tiles_states_strings.xml b/packages/SystemUI/res/values-gu/tiles_states_strings.xml
index 196a05b..5c4a478 100644
--- a/packages/SystemUI/res/values-gu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-gu/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"બંધ છે"</item>
<item msgid="4875147066469902392">"ચાલુ છે"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"અનુપલબ્ધ"</item>
- <item msgid="2004750556637773692">"બંધ"</item>
- <item msgid="8968530753931637871">"ચાલુ"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"ઉપલબ્ધ નથી"</item>
<item msgid="5044688398303285224">"બંધ છે"</item>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index b3c861f..6d96376 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"परफ़ॉर्मेंस"</string>
<string name="user_interface" msgid="3712869377953950887">"यूज़र इंटरफ़ेस"</string>
<string name="thermal" msgid="6758074791325414831">"थर्मल"</string>
+ <string name="custom" msgid="3337456985275158299">"कस्टम"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"कस्टम ट्रेस सेटिंग"</string>
+ <string name="restore_default" msgid="5259420807486239755">"डिफ़ॉल्ट सेटिंग वापस लाएं"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"वन-हैंडेड मोड"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"कान की मशीनें"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"ऐक्टिव"</string>
@@ -431,6 +434,12 @@
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"सेटिंग"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"चालू है"</string>
<string name="zen_mode_off" msgid="1736604456618147306">"बंद है"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
+ <skip />
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
+ <skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"आपको अलार्म, रिमाइंडर, इवेंट और चुनिंदा कॉल करने वालों के अलावा किसी और तरह से (आवाज़ करके और थरथरा कर ) परेशान नहीं किया जाएगा. आप फिर भी संगीत, वीडियो और गेम सहित अपना चुना हुआ सब कुछ सुन सकते हैं."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"आपको अलार्म छोड़कर दूसरी आवाज़ों और कंपनों से परेशान नहीं किया जाएगा. आपको अब भी संगीत, वीडियो और गेम सहित वह सब कुछ सुनाई देगा जो आपने चलाने के लिए चुना है."</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"अपनी पसंद के मुताबिक बनाएं"</string>
@@ -469,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • धीरे चार्ज हो रहा है • <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> • चार्ज हो रहा है • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा चार्ज हो जाएगा"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"लॉक स्क्रीन पर विजेट"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"कम्यूनिटी ट्यूटोरियल शुरू करने के लिए, बाईं ओर स्वाइप करें"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"पसंद के मुताबिक बनाएं"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"खारिज करें"</string>
@@ -554,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"अभी शुरू करें"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"कोई सूचना नहीं है"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"कोई नई सूचना नहीं है"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"नोटिफ़िकेशन कूलडाउन की सेटिंग चालू है"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"एक साथ कई सूचनाएं मिलने पर, डिवाइस में सूचनाओं से होने वाली आवाज़ और सूचनाएं, दो मिनट के लिए अपने-आप कम हो जाएंगी."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"बंद करें"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"पुरानी सूचाएं देखने के लिए अनलॉक करें"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"इस डिवाइस का प्रबंधन आपके अभिभावक करते हैं"</string>
@@ -1223,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"पुष्टि करना ज़रूरी है. पुष्टि करने के लिए, फ़िंगरप्रिंट सेंसर को छुएं."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"फ़ोन कॉल चल रहा है"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"कनेक्ट हो गया"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"इंटरनेट कनेक्शन कुछ समय के लिए है"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"इंटरनेट कनेक्शन खराब है"</string>
@@ -1377,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"हो गया"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"बहुत बढ़िया!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"वापस जाएं"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"वापस जाने के लिए, टचपैड पर कहीं भी तीन उंगलियों से बाईं या दाईं तरफ़ स्वाइप करें."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"टचपैड पर तीन उंगलियों को दाईं और बाईं तरफ़ ले जाया जा रहा है"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"डिवाइस की स्क्रीन पर, पिछले पेज पर जाने के लिए हाथ के जेस्चर का ऐनिमेशन दिख रहा है"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"कीबोर्ड की बैकलाइट"</string>
diff --git a/packages/SystemUI/res/values-hi/tiles_states_strings.xml b/packages/SystemUI/res/values-hi/tiles_states_strings.xml
index b988d72..b89eeb3 100644
--- a/packages/SystemUI/res/values-hi/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hi/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"बंद है"</item>
<item msgid="4875147066469902392">"चालू है"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"उपलब्ध नहीं है"</item>
- <item msgid="2004750556637773692">"बंद है"</item>
- <item msgid="8968530753931637871">"चालू है"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"उपलब्ध नहीं है"</item>
<item msgid="5044688398303285224">"बंद है"</item>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 3bd6c64..1d5051c 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Izvedba"</string>
<string name="user_interface" msgid="3712869377953950887">"Korisničko sučelje"</string>
<string name="thermal" msgid="6758074791325414831">"Termalno"</string>
+ <string name="custom" msgid="3337456985275158299">"Prilagođeno"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Postavke prilagođenog praćenja"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Vrati na zadano"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Način rada jednom rukom"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Slušna pomagala"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktivno"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritetni načini"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gotovo"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Postavke"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Uključeno"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Isključeno"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Neće vas ometati zvukovi i vibracije, osim alarma, podsjetnika, događaja i pozivatelja koje navedete. I dalje ćete čuti sve što želite reproducirati, uključujući glazbu, videozapise i igre."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Neće vas ometati zvukovi i vibracije, osim alarma. I dalje ćete čuti sve što želite reproducirati, uključujući glazbu, videozapise i igre."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • sporo punjenje • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti"</string>
<string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • punjenje • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgeti na zaključanom zaslonu"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Prijeđite prstom ulijevo da biste pokrenuli zajednički vodič"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prilagodi"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Odbaci"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"postavi odabrani widget"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgeti zaključanog zaslona"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Svi vide widgete na vašem zaključanom zaslonu, čak i ako je tablet zaključan."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"poništavanje odabira widgeta"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgeti na zaključanom zaslonu"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Da biste otvorili aplikaciju pomoću widgeta, trebate potvrditi da ste to vi. Također napominjemo da ih svatko može vidjeti, čak i ako je vaš tablet zaključan. Neki widgeti možda nisu namijenjeni za zaključani zaslon, pa ih možda nije sigurno dodati ovdje."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Shvaćam"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Pokreni"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Nema obavijesti"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Nema novih obavijesti"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Stišavanje obavijesti je uključeno"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Glasnoća/upozorenja uređaja automatski se stišavaju do 2 min kad primite previše obavijesti odjednom"</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Isključi"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Otključajte za starije obavijesti"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Ovim uređajem upravlja tvoj roditelj"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Potrebna je autentifikacija. Dodirnite senzor otiska prsta da biste se autentificirali."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonski poziv u tijeku"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilni podaci"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Privremeno povezano"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Slaba veza"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gotovo"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Sjajno!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Natrag"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Za povratak trima prstima prijeđite ulijevo ili udesno bilo gdje na dodirnoj podlozi."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Dodirna podloga prikazuje tri prsta koji se kreću udesno i ulijevo"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Na zaslonu uređaja prikazuje se animacija za pokret za povratak"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Pozadinsko osvjetljenje tipkovnice"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Upravljanje uređajima"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Brzo upravljajte uređajima putem čuvara zaslona"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Poništi"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Za povratak prijeđite ulijevo ili udesno trima prstima na dodirnoj podlozi"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Da biste se vratili na početni zaslon, prijeđite prema gore trima prstima na dodirnoj podlozi."</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Za prikaz nedavnih aplikacija prijeđite prema gore trima prstima i zadržite pritisak na dodirnoj podlozi"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Za prikaz svojih svih aplikacija pritisnite tipku za radnju na tipkovnici"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Upotrijebite dodirnu podlogu za povratak"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Prijeđite ulijevo ili udesno trima prstima. Dodirnite da biste naučili više pokreta."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Uz pomoć dodirne podloge vratite se na početni zaslon"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Prijeđite prema gore trima prstima. Dodirnite da biste naučili više pokreta."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Upotrijebite dodirnu podlogu za prikaz nedavnih aplikacija"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Prijeđite prema gore trima prstima i zadržite pritisak. Dodirnite da biste naučili više pokreta."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Upotrijebite tipkovnicu za prikaz svih aplikacija"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pritisnite tipku za radnju u bilo kojem trenutku. Dodirnite da biste naučili više pokreta."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/tiles_states_strings.xml b/packages/SystemUI/res/values-hr/tiles_states_strings.xml
index be48b3b..df0b786 100644
--- a/packages/SystemUI/res/values-hr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hr/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Isključeno"</item>
<item msgid="4875147066469902392">"Uključeno"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Nedostupno"</item>
- <item msgid="2004750556637773692">"Isključeno"</item>
- <item msgid="8968530753931637871">"Uključeno"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Nedostupno"</item>
<item msgid="5044688398303285224">"Isključeno"</item>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 7a0325e..0604064 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Teljesítmény"</string>
<string name="user_interface" msgid="3712869377953950887">"Kezelőfelület"</string>
<string name="thermal" msgid="6758074791325414831">"Termikus"</string>
+ <string name="custom" msgid="3337456985275158299">"Egyéni"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Egyéni nyombeállítások"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Alapértelmezett érték visszaállítása"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Egykezes mód"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hallókészülékek"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktív"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritási módok"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Kész"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Beállítások"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Be"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Ki"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Az Ön által meghatározott ébresztéseken, emlékeztetőkön, eseményeken és hívókon kívül nem fogja Önt más hang vagy rezgés megzavarni. Továbbra is lesz hangjuk azoknak a tartalmaknak, amelyeket Ön elindít, például zenék, videók és játékok."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Az ébresztéseken kívül nem fogja Önt más hang és rezgés megzavarni. Továbbra is lesz hangjuk azoknak a tartalmaknak, amelyeket Ön elindít, például zenék, videók és játékok."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lassú töltés • A teljes töltöttségig: <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> • Töltés • A teljes töltöttségig: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Modulok a lezárási képernyőn"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Csúsztasson gyorsan balra a közösségi útmutató elindításához"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Személyre szabás"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Elvetés"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"kijelölt modul áthelyezése"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"A lezárási képernyő moduljai"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Bárki megtekintheti a modulokat a lezárási képernyőjén, még ha a táblagépe zárolva is van."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"modul kijelölésének megszüntetése"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"A lezárási képernyő moduljai"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Ha modul használatával szeretne megnyitni egy alkalmazást, igazolnia kell a személyazonosságát. Ne felejtse továbbá, hogy bárki megtekintheti a modulokat, még akkor is, amikor zárolva van a táblagép. Előfordulhat, hogy bizonyos modulokat nem a lezárási képernyőn való használatra terveztek, ezért nem biztonságos a hozzáadásuk."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Értem"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Indítás most"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Nincs értesítés"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Nincsenek új értesítések"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Értesítések befagyasztása bekapcsolva"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Az eszköz hangerejét és értesítéseit a rendszer automatikusan legfeljebb két percig csökkenti, ha egyszerre túl sok értesítést kap."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Igen"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"A régebbiek feloldás után láthatók"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Az eszközt a szülőd felügyeli"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Hitelesítés szükséges. Érintse meg az ujjlenyomat-érzékelőt a hitelesítéshez."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Folyamatban lévő telefonhívás"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiladat"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="NETWORKMODE">%2$s</xliff:g>/<xliff:g id="STATE">%1$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Csatlakozva"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Ideiglenesen csatlakoztatva"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Gyenge kapcsolat"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Kész"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Kiváló!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Vissza"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"A visszalépéshez csúsztasson három ujjal gyorsan balra vagy a jobbra az érintőpad tetszőleges területén."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Három, jobbra és balra mozgó ujjat ábrázoló érintőpad"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"A Vissza kézmozdulat animációját megjelenítő eszközképernyő"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"A billentyűzet háttérvilágítása"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Otthon vezérlése"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Gyorsan vezérelheti otthonát képernyőkímélővel"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Visszavonás"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"A visszalépéshez csúsztasson három ujjal balra vagy a jobbra az érintőpadon."</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"A kezdőképernyőre való ugráshoz csúsztasson felfelé három ujjal az érintőpadon."</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"A legutóbbi appokért csúsztasson lefelé három ujjal az érintőpadon, és tartsa lenyomva ujjait."</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Az összes alkalmazás megtekintéséhez nyomja meg a billentyűzet műveletbillentyűjét."</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"A visszalépéshez használja az érintőpadot"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Csúsztatasson gyorsan három ujjal balra vagy jobbra. Koppintson a további kézmozdulatokért."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"A kezdőképernyő megnyitásához használja az érintőpadot"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Túsztasson felfelé három ujjal. Koppintson a további kézmozdulatokért."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"A legutóbbi alkalmazások megtekintéséhez használja az érintőpadot"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Gyúsztason felfelé három ujjal, és tartsa lenyomva az ujjait. Koppintson a további kézmozdulatokért."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"A billentyűzet használatával valamennyi alkalmazás megtekinthető"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"A műveletbillentyű bármikor használható. Koppintson a további kézmozdulatokért."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/tiles_states_strings.xml b/packages/SystemUI/res/values-hu/tiles_states_strings.xml
index ef23a29..bbd6bc0 100644
--- a/packages/SystemUI/res/values-hu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hu/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Ki"</item>
<item msgid="4875147066469902392">"Be"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Nem áll rendelkezésre"</item>
- <item msgid="2004750556637773692">"Ki"</item>
- <item msgid="8968530753931637871">"Be"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Nem áll rendelkezésre"</item>
<item msgid="5044688398303285224">"Ki"</item>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index afe7920..6f32125 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Արդյունավետություն"</string>
<string name="user_interface" msgid="3712869377953950887">"Օգտատիրական ինտերֆեյս"</string>
<string name="thermal" msgid="6758074791325414831">"Ջերմատեսիլ"</string>
+ <string name="custom" msgid="3337456985275158299">"Հատուկ"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Հետագծման հատուկ կարգավորումներ"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Վերականգնել կանխադրված կարգավորումները"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Մեկ ձեռքի ռեժիմ"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Լսողական սարքեր"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Ակտիվ է"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Կարևոր ռեժիմներ"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Պատրաստ է"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Կարգավորումներ"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Միացված է"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Անջատված է"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Ձայները և թրթռոցները չեն անհանգստացնի ձեզ, բացի ձեր կողմից նշված զարթուցիչները, հիշեցումները, միջոցառումների ծանուցումները և զանգերը։ Դուք կլսեք ձեր ընտրածի նվագարկումը, այդ թվում՝ երաժշտություն, տեսանյութեր և խաղեր:"</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Ձայները և թրթռոցները, բացի զարթուցիչներից, չեն անհանգստացնի ձեզ: Դուք կլսեք ձեր ընտրածի նվագարկումը, այդ թվում՝ երաժշտություն, տեսանյութեր և խաղեր:"</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Դանդաղ լիցքավորում • Մնացել է <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> • Լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Վիջեթներ կողպէկրանին"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Թերթեք ձախ՝ ուղեցույցը գործարկելու համար"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Անհատականացնել"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Փակել"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"տեղադրել ընտրված վիջեթը"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Կողպէկրանի վիջեթներ"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Բոլորը կարող են դիտել ձեր կողպէկրանի վիջեթները, նույնիսկ եթե պլանշետը կողպված է"</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"չեղարկել վիջեթի ընտրությունը"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Կողպէկրանի վիջեթներ"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Վիջեթի միջոցով հավելված բացելու համար դուք պետք է հաստատեք ձեր ինքնությունը։ Նաև նկատի ունեցեք, որ ցանկացած ոք կարող է դիտել վիջեթները, նույնիսկ երբ ձեր պլանշետը կողպված է։ Որոշ վիջեթներ կարող են նախատեսված չլինել ձեր կողպէկրանի համար, և այստեղ դրանց ավելացնելը կարող է վտանգավոր լինել։"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Եղավ"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Սկսել հիմա"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Ծանուցումներ չկան"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Նոր ծանուցումներ չկան"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Ծանուցումների ձայնի իջեցումը միացված է"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Սարքի և ծանուցումների ձայնն ավտոմատ իջեցվում է մինչև 2 րոպե, երբ շատ ծանուցումներ եք ստանում։"</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Անջատել"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Ապակողպեք՝ տեսնելու հին ծանուցումները"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Այս սարքը կառավարում է ձեր ծնողը"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Պահանջվում է նույնականացում։ Դրա համար մատը հպեք մատնահետքի սկաներին։"</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ընթացիկ հեռախոսազանգ"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Բջջային ինտերնետ"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Միացած է"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Ժամանակավոր կապ"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Թույլ կապ"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Պատրաստ է"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Կեցցե՛ք"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Հետ գնալ"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Հետ գնալու համար հպահարթակի վրա երեք մատով սահեցրեք ձախ կամ աջ։"</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Երեք մատները աջ ու ձախ են շարժվում հպահարթակի վրա"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Սարքի էկրանին ցուցադրվում է շարժանկար՝ հետ գնալու ժեստի համար"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Հետին լուսավորությամբ ստեղնաշար"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Տան կառավարման տարրեր"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Տան կառավարման տարրերը դարձրեք էկրանապահ"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Հետարկել"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Հետ գնալու համար հպահարթակի վրա երեք մատը սահեցրեք ձախ կամ աջ"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Հիմնական էկրան անցնելու համար հպահարթակի վրա երեք մատը սահեցրեք ձախ կամ աջ"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Վերջերս օգտագործված հավելվածները դիտելու համար երեք մատը սահեցրեք վերև և սեղմած պահեք"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Բոլոր հավելվածները դիտելու համար սեղմեք գործողության ստեղնը ստեղնաշարի վրա"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Օգտագործեք ձեր հպահարթակը՝ վերադառնալու համար"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Երեք մատը սահեցրեք ձախ կամ աջ։ Հպեք՝ ավելի շատ ժեստերի ծանոթանալու համար։"</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Օգտագործեք ձեր հպահարթակը՝ հիմնական էկրան անցնելու համար"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Երեք մատը սահեցրեք վերև։ Հպեք՝ ավելի շատ ժեստերի ծանոթանալու համար։"</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Օգտագործեք ձեր հպահարթակը՝ վերջերս օգտագործված հավելվածները դիտելու համար"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Երեք մատը սահեցրեք վերև և սեղմած պահեք։ Հպեք՝ ավելի շատ ժեստերի ծանոթանալու համար։"</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Օգտագործեք ձեր ստեղնաշարը՝ բոլոր հավելվածները դիտելու համար"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Ցանկացած ժամանակ սեղմեք գործողության ստեղնը։ Հպեք՝ ավելի շատ ժեստերի ծանոթանալու համար։"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy/tiles_states_strings.xml b/packages/SystemUI/res/values-hy/tiles_states_strings.xml
index 0f951f6..eb77ccf 100644
--- a/packages/SystemUI/res/values-hy/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hy/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Անջատված է"</item>
<item msgid="4875147066469902392">"Միացված է"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Հասանելի չէ"</item>
- <item msgid="2004750556637773692">"Անջատված է"</item>
- <item msgid="8968530753931637871">"Միացված է"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Հասանելի չէ"</item>
<item msgid="5044688398303285224">"Անջատված է"</item>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 0e30a3c..873372b 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Performa"</string>
<string name="user_interface" msgid="3712869377953950887">"Antarmuka Pengguna"</string>
<string name="thermal" msgid="6758074791325414831">"Termal"</string>
+ <string name="custom" msgid="3337456985275158299">"Kustom"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Setelan Rekaman Aktivitas Kustom"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Pulihkan Default"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Mode satu tangan"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Alat bantu dengar"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktif"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Mode prioritas"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Selesai"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Setelan"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Aktif"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Nonaktif"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Anda tidak akan terganggu oleh suara dan getaran, kecuali dari alarm, pengingat, acara, dan penelepon yang Anda tentukan. Anda akan tetap mendengar apa pun yang telah dipilih untuk diputar, termasuk musik, video, dan game."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Anda tidak akan terganggu oleh suara dan getaran, kecuali dari alarm. Anda akan tetap mendengar apa pun yang telah dipilih untuk diputar, termasuk musik, video, dan game."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya dengan lambat • Penuh dalam waktu <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> • Mengisi daya • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widget di layar kunci"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Geser ke kiri untuk memulai tutorial komunal"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Sesuaikan"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Tutup"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"letakkan widget yang dipilih"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Widget layar kunci"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Siapa saja dapat melihat widget di layar kunci Anda, meskipun tablet terkunci."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"batalkan pilihan widget"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widget layar kunci"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Untuk membuka aplikasi menggunakan widget, Anda perlu memverifikasi diri Anda. Selain itu, harap ingat bahwa siapa saja dapat melihatnya, bahkan saat tablet Anda terkunci. Beberapa widget mungkin tidak dirancang untuk layar kunci Anda dan mungkin tidak aman untuk ditambahkan di sini."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Oke"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Mulai sekarang"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Tidak ada notifikasi"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Tidak ada notifikasi baru"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Pengurangan suara dan getaran notifikasi aktif"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Saat Anda menerima terlalu banyak notifikasi sekaligus, volume dan notifikasi perangkat akan otomatis dikurangi hingga selama 2 menit."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Nonaktifkan"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Buka kunci untuk melihat notifikasi lama"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Perangkat ini dikelola oleh orang tuamu"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Perlu autentikasi. Sentuh sensor sidik jari untuk melakukan autentikasi."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Panggilan telepon sedang berlangsung"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Data seluler"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Terhubung"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Terhubung sementara"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Koneksi buruk"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Selesai"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Bagus!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Kembali"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Untuk kembali, geser ke kiri atau ke kanan menggunakan tiga jari ke mana saja di touchpad."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad menampilkan tiga jari yang bergerak ke kanan dan ke kiri"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Layar perangkat menampilkan animasi untuk gestur kembali"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Lampu latar keyboard"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrol Rumah"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Akses cepat kontrol rumah Anda sebagai screensaver"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Urungkan"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Untuk kembali, geser ke kiri atau kanan menggunakan tiga jari di touchpad"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Untuk membuka layar utama, geser ke atas menggunakan tiga jari di touchpad"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Untuk melihat aplikasi terkini, geser ke atas dan tahan menggunakan tiga jari di touchpad"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Untuk melihat semua aplikasi, tekan tombol tindakan di keyboard"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Gunakan touchpad untuk kembali"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Geser ke kiri atau kanan menggunakan tiga jari. Ketuk untuk mempelajari gestur lainnya."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Gunakan touchpad untuk membuka layar utama"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Geser ke atas menggunakan tiga jari. Ketuk untuk mempelajari gestur lainnya."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Gunakan touchpad untuk melihat aplikasi terkini"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Geser ke atas dan tahan menggunakan tiga jari. Ketuk untuk mempelajari gestur lainnya."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Gunakan keyboard untuk melihat semua aplikasi"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Tekan tombol tindakan kapan saja. Ketuk untuk mempelajari gestur lainnya."</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/tiles_states_strings.xml b/packages/SystemUI/res/values-in/tiles_states_strings.xml
index f05d99d..a415f64 100644
--- a/packages/SystemUI/res/values-in/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-in/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Nonaktif"</item>
<item msgid="4875147066469902392">"Aktif"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Tidak tersedia"</item>
- <item msgid="2004750556637773692">"Nonaktif"</item>
- <item msgid="8968530753931637871">"Aktif"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Tidak tersedia"</item>
<item msgid="5044688398303285224">"Mati"</item>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 2fc7073..50145b0 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Afköst"</string>
<string name="user_interface" msgid="3712869377953950887">"Notandaviðmót"</string>
<string name="thermal" msgid="6758074791325414831">"Varmi"</string>
+ <string name="custom" msgid="3337456985275158299">"Sérsnið"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Sérsniðnar rakningarstillingar"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Endurheimta sjálfgildi"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Einhent stilling"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Heyrnartæki"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Virk"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Forgangsstillingar"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Lokið"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Stillingar"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Kveikt"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Slökkt"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Þú verður ekki fyrir truflunum frá hljóðmerkjum og titringi, fyrir utan vekjara, áminningar, viðburði og símtöl frá þeim sem þú leyfir fyrirfram. Þú heyrir áfram í öllu sem þú velur að spila, svo sem tónlist, myndskeiðum og leikjum."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Þú verður ekki fyrir truflunum frá hljóðmerkjum og titringi, fyrir utan vekjara. Þú heyrir áfram í öllu sem þú velur að spila, svo sem tónlist, myndskeiðum og leikjum."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hæg hleðsla • Full hleðsla eftir <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> • Í hleðslu • Full hleðsla eftir <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Græjur á lásskjá"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Strjúktu til vinstri til að hefja samfélagsleiðsögnina"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Sérsníða"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Hunsa"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"koma valinni græju fyrir"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Græjur á lásskjá"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Hver sem er getur séð græjur á lásskjánum þínum, jafnvel þótt spjaldtölvan sé læst."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"afturkalla val á græju"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Græjur fyrir lásskjá"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Þú þarft að staðfesta að þetta sért þú til að geta opnað forrit með græju. Hafðu einnig í huga að hver sem er getur skoðað þær, jafnvel þótt spjaldtölvan sé læst. Sumar græjur eru hugsanlega ekki ætlaðar fyrir lásskjá og því gæti verið óöruggt að bæta þeim við hér."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Ég skil"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Byrja núna"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Engar tilkynningar"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Engar nýjar tilkynningar"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Kveikt er á tilkynningadempun"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Lækkað er sjálfkrafa í hljóðstyrk og áminningum tækisins í allt að tvær mínútur þegar þú færð of margar tilkynningar í einu."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Slökkva"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Taktu úr lás til að sjá eldri tilkynningar"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Foreldri þitt stjórnar þessu tæki"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Auðkenningar krafist. Auðkenndu með því að snerta fingrafaralesarann."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Símtal í gangi"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Farsímagögn"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Tengt"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tímabundin tenging"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Léleg tenging"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Lokið"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Vel gert!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Til baka"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Strjúktu til vinstri eða hægri með þrem fingrum hvar sem er á snertifletinum til að fara til baka."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Snertiflötur sem sýnir þrjá fingur færast til hægri og vinstri"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Skjár tækis sem sýnir hreyfimynd fyrir bendinguna „til baka“."</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Baklýsing lyklaborðs"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Heimastýringar"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Fáðu skjótan aðgang að heimastýringum sem skjávara"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Afturkalla"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Strjúktu til vinstri eða hægri með þremur fingrum á snertifletinum til að fara til baka"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Strjúktu upp með þremur fingrum á snertifletinum til að fara á heimaskjá"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Strjúktu upp og haltu með þremur fingrum á snertifletinum til að sjá nýleg forrit"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Ýttu á aðgerðalykilinn á lyklaborðinu til að sjá öll forritin þín"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Notaðu snertiflötinn til að fara til baka"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Strjúktu til vinstri eða hægri með þremur fingrum. Ýttu til að læra fleiri bendingar."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Notaðu snertiflötinn til að fara á heimaskjá"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Strjúktu upp með þremur fingrum. Ýttu til að læra fleiri bendingar."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Notaðu snertiflötinn til að sjá nýleg forrit"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Strjúktu upp og haltu með þremur fingrum. Ýttu til að læra fleiri bendingar."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Notaðu lyklaborðið til að sjá öll forrit"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Ýttu hvenær sem er á aðgerðalykilinn. Ýttu til að læra fleiri bendingar."</string>
</resources>
diff --git a/packages/SystemUI/res/values-is/tiles_states_strings.xml b/packages/SystemUI/res/values-is/tiles_states_strings.xml
index d13075e..c9befd6 100644
--- a/packages/SystemUI/res/values-is/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-is/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Slökkt"</item>
<item msgid="4875147066469902392">"Kveikt"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Ekki tiltækt"</item>
- <item msgid="2004750556637773692">"Slökkt"</item>
- <item msgid="8968530753931637871">"Kveikt"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Ekki í boði"</item>
<item msgid="5044688398303285224">"Slökkt"</item>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index d36d8cc..502678e 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -390,6 +390,9 @@
<string name="performance" msgid="6552785217174378320">"Prestazioni"</string>
<string name="user_interface" msgid="3712869377953950887">"Interfaccia utente"</string>
<string name="thermal" msgid="6758074791325414831">"Termico"</string>
+ <string name="custom" msgid="3337456985275158299">"Personalizzate"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Impostazioni monitoraggio personalizzate"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Ripristina predefinite"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modalità a una mano"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Apparecchi acustici"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Attivi"</string>
@@ -431,10 +434,11 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modalità priorità"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Fine"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Impostazioni"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
- <skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
- <skip />
+ <string name="zen_mode_on" msgid="9085304934016242591">"On"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Off"</string>
+ <string name="zen_mode_set_up" msgid="7457957033034460064">"Configura"</string>
+ <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Gestisci nelle impostazioni"</string>
+ <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nessuna modalità attiva}=1{{mode} è attiva}many{# di modalità sono attive}other{# modalità sono attive}}"</string>
<string name="zen_priority_introduction" msgid="3159291973383796646">"Suoni e vibrazioni non ti disturberanno, ad eccezione di sveglie, promemoria, eventi, chiamate da contatti da te specificati ed elementi che hai scelto di continuare a riprodurre, inclusi video, musica e giochi."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Non riceverai distrazioni da suoni e vibrazioni, ad eccezione delle sveglie. Potrai comunque sentire qualunque cosa decidi di riprodurre, inclusi video, musica e giochi."</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"Personalizza"</string>
@@ -473,6 +477,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ricarica lenta • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> alla ricarica completa"</string>
<string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • In carica • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> alla ricarica completa"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widget su schermata di blocco"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Scorri a sinistra per iniziare il tutorial della community"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizza"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Chiudi"</string>
@@ -501,8 +507,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"posiziona il widget selezionato"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Widget della schermata di blocco"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Chiunque può visualizzare i widget sulla tua schermata di blocco, anche se il tablet è bloccato."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"deseleziona widget"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widget della schermata di blocco"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Per aprire un\'app utilizzando un widget, dovrai verificare la tua identità. Inoltre tieni presente che chiunque può vederlo, anche quando il tablet è bloccato. Alcuni widget potrebbero non essere stati progettati per la schermata di blocco e potrebbe non essere sicuro aggiungerli qui."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Ok"</string>
@@ -559,10 +564,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Avvia adesso"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Nessuna notifica"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Nessuna nuova notifica"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Attenuazione delle notifiche attivata"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Volume e avvisi sono ridotti automaticamente fino a 2 minuti quando ricevi troppe notifiche insieme."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Disattiva"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Sblocca per vedere le notifiche meno recenti"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Questo dispositivo è gestito dai tuoi genitori"</string>
@@ -1228,7 +1231,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticazione obbligatoria. Eseguila toccando il sensore di impronte digitali."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonata in corso"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Dati mobili"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Connessa"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connessa temporaneamente"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Connessione debole"</string>
@@ -1382,7 +1384,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Fine"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Ottimo lavoro"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Indietro"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Per tornare indietro, scorri verso sinistra o verso destra utilizzando tre dita in un punto qualsiasi del touchpad."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad che mostra tre dita che si muovono verso destra e sinistra"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Schermata del dispositivo che mostra l\'animazione del gesto per tornare indietro"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroilluminazione della tastiera"</string>
@@ -1390,28 +1395,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Controlli della casa"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Accedi rapidamente ai controlli della casa dal salvaschermo"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Annulla"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Per tornare indietro, scorri verso sinistra o verso destra con tre dita sul touchpad."</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Per andare alla schermata Home, scorri verso l\'alto con tre dita sul touchpad"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Per visualizzare le app recenti, scorri verso l\'alto e tieni premuto con tre dita sul touchpad"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Per visualizzare tutte le tue app, premi il tasto azione sulla tastiera"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Usa il touchpad per tornare indietro"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Scorri verso sinistra o destra con tre dita. Tocca per scoprire altri gesti."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Usa il touchpad per andare alla schermata Home"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Scorri verso l\'altro con tre dita. Tocca per scoprire altri gesti."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Usa il touchpad per visualizzare le app recenti"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Scorri verso l\'alto e tieni premuto con tre dita. Tocca per scoprire altri gesti."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Usa la tastiera per visualizzare tutte le app"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Premi il tasto azione in qualsiasi momento. Tocca per scoprire altri gesti."</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/tiles_states_strings.xml b/packages/SystemUI/res/values-it/tiles_states_strings.xml
index 95c33c4..2fd4f6d 100644
--- a/packages/SystemUI/res/values-it/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-it/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Off"</item>
<item msgid="4875147066469902392">"On"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Non disponibile"</item>
- <item msgid="2004750556637773692">"Off"</item>
- <item msgid="8968530753931637871">"On"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Non disponibile"</item>
<item msgid="5044688398303285224">"Off"</item>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 553b23d..698d2ad 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -138,13 +138,13 @@
<string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"מתבצע כרגע שיתוף של אפליקציה"</string>
<string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"הפסקת השיתוף"</string>
<string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"הפעלת Cast של המסך מתבצעת"</string>
- <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"להפסיק את הפעלת ה-Cast?"</string>
- <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"מתבצעת כרגע הפעלת Cast של כל המסך שלך למכשיר <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
- <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"מתבצעת כרגע הפעלת Cast של כל המסך שלך למכשיר בקרבת מקום"</string>
- <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"מתבצעת כרגע הפעלת Cast של <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> למכשיר <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
- <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"מתבצעת כרגע הפעלת Cast של <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> למכשיר בקרבת מקום"</string>
- <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"מתבצעת כרגע הפעלת Cast למכשיר <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
- <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"מתבצעת כרגע הפעלת Cast למכשיר בקרבת מקום"</string>
+ <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"להפסיק את פעולת ה-Cast?"</string>
+ <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"מתבצעת כרגע פעולת Cast של כל המסך שלך למכשיר <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"מתבצעת כרגע פעולת Cast של כל המסך שלך למכשיר בקרבת מקום"</string>
+ <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"מתבצעת כרגע פעולת Cast של <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> למכשיר <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"מתבצעת כרגע פעולת Cast של <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> למכשיר בקרבת מקום"</string>
+ <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"מתבצעת כרגע פעולת Cast למכשיר <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"מתבצעת כרגע פעולת Cast למכשיר בקרבת מקום"</string>
<string name="cast_to_other_device_stop_dialog_button" msgid="6420183747435521834">"הפסקת ה-Cast"</string>
<string name="close_dialog_button" msgid="4749497706540104133">"סגירה"</string>
<string name="issuerecord_title" msgid="286627115110121849">"בעיה במכשיר ההקלטה"</string>
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"ביצועים"</string>
<string name="user_interface" msgid="3712869377953950887">"ממשק משתמש"</string>
<string name="thermal" msgid="6758074791325414831">"תרמי"</string>
+ <string name="custom" msgid="3337456985275158299">"בהתאמה אישית"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"הגדרות מעקב מותאמות אישית"</string>
+ <string name="restore_default" msgid="5259420807486239755">"שחזור של ברירת המחדל"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"מצב שימוש ביד אחת"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"מכשירי שמיעה"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"פעיל"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"מצבי עדיפות"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"סיום"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"הגדרות"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"מצב מופעל"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"מצב מושבת"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"כדי לא להפריע לך, המכשיר לא ירטוט ולא ישמיע שום צליל, חוץ מהתראות, תזכורות, אירועים ושיחות ממתקשרים מסוימים לבחירתך. המצב הזה לא ישפיע על צלילים שהם חלק מתוכן שבחרת להפעיל, כמו מוזיקה, סרטונים ומשחקים."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"כדי לא להפריע לך, המכשיר לא ירטוט ולא ישמיע שום צליל, חוץ מהתראות. המצב הזה לא ישפיע על צלילים שהם חלק מתוכן שבחרת להפעיל, כמו מוזיקה, סרטונים ומשחקים."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה איטית • <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> • בטעינה • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ווידג\'טים במסך הנעילה"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"אפשר להחליק שמאלה כדי להפעיל את המדריך המשותף"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"התאמה אישית"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"סגירה"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"צריך למקם את הווידג\'ט שנבחר"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"ווידג\'טים במסך הנעילה"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"כולם יכולים לראות את הווידג\'טים במסך הנעילה שלך, גם אם הטאבלט נעול."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ביטול הבחירה בווידג\'ט"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ווידג\'טים במסך הנעילה"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"כדי לפתוח אפליקציה באמצעות ווידג\'ט, עליך לאמת את זהותך. בנוסף, כדאי לזכור שכל אחד יכול לראות את הווידג\'טים גם כשהטאבלט שלך נעול. יכול להיות שחלק מהווידג\'טים לא נועדו למסך הנעילה ושלא בטוח להוסיף אותם לכאן."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"הבנתי"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"כן, אפשר להתחיל"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"אין התראות"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"אין התראות חדשות"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"הפוגת ההתראות מופעלת"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"עוצמת הקול וההתראות במכשיר מופחתות אוטומטית למשך עד 2 דקות כשמתקבלות יותר מדי התראות בבת אחת."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"השבתה"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"יש לבטל את הנעילה כדי לראות התראות ישנות"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"המכשיר הזה מנוהל על ידי ההורה שלך"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"נדרש אימות. יש לגעת בחיישן טביעות האצבע כדי לבצע אימות."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"מתקיימת שיחה"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"חבילת גלישה"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"מחובר"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"מחובר באופן זמני"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"חיבור באיכות ירודה"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"סיום"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"מעולה!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"חזרה"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"כדי לחזור אחורה, מחליקים שמאלה או ימינה עם שלוש אצבעות בכל מקום על לוח המגע."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"לוח מגע שמראה שלוש אצבעות זזות ימינה ושמאלה"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"מסך מכשיר שמראה אנימציה לתנועה אחורה"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"התאורה האחורית במקלדת"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"שליטה במכשירים"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"גישה מהירה לממשק השליטה במכשירים כשומר מסך"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"ביטול"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"כדי לחזור אחורה, מחליקים שמאלה או ימינה עם שלוש אצבעות על לוח המגע."</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"כדי לעבור למסך הבית, מחליקים למעלה עם שלוש אצבעות על לוח המגע"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"כדי לראות את האפליקציות האחרונות, מחליקים למעלה עם שלוש אצבעות על לוח המגע ולוחצים לחיצה ארוכה"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"כדי לראות את כל האפליקציות, מקישים על מקש הפעולה במקלדת"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"איך להשתמש בלוח המגע כדי לחזור אחורה"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"מחליקים ימינה או שמאלה עם שלוש אצבעות. ניתן להקיש כדי לקבל מידע נוסף על התנועות."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"איך להשתמש בלוח המגע כדי לעבור למסך הבית"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"מחליקים למעלה עם שלוש אצבעות. ניתן להקיש כדי לקבל מידע נוסף על התנועות."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"איך להשתמש בלוח המגע כדי לראות את האפליקציות האחרונות"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"מחליקים למעלה ולוחצים לחיצה ארוכה עם שלוש אצבעות. ניתן להקיש כדי לקבל מידע נוסף על התנועות."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"איך להשתמש במקלדת כדי לראות את כל האפליקציות"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"בכל שלב אפשר ללחוץ על מקש הפעולה. ניתן להקיש כדי לקבל מידע נוסף על התנועות."</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/tiles_states_strings.xml b/packages/SystemUI/res/values-iw/tiles_states_strings.xml
index 86edca8..b5cb476 100644
--- a/packages/SystemUI/res/values-iw/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-iw/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"כבוי"</item>
<item msgid="4875147066469902392">"פועל"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"לא זמין"</item>
- <item msgid="2004750556637773692">"מצב מושבת"</item>
- <item msgid="8968530753931637871">"מצב מופעל"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"לא זמין"</item>
<item msgid="5044688398303285224">"כבוי"</item>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 7a75998..7e09b94 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"パフォーマンス"</string>
<string name="user_interface" msgid="3712869377953950887">"ユーザー インターフェース"</string>
<string name="thermal" msgid="6758074791325414831">"温度"</string>
+ <string name="custom" msgid="3337456985275158299">"カスタム"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"カスタム トレース設定"</string>
+ <string name="restore_default" msgid="5259420807486239755">"デフォルトに戻す"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"片手モード"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"補聴器"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"アクティブ"</string>
@@ -431,6 +434,9 @@
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"設定"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"ON"</string>
<string name="zen_mode_off" msgid="1736604456618147306">"OFF"</string>
+ <string name="zen_mode_set_up" msgid="7457957033034460064">"設定"</string>
+ <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"設定で管理"</string>
+ <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{アクティブなモードはありません}=1{{mode} がアクティブです}other{# 個のモードがアクティブです}}"</string>
<string name="zen_priority_introduction" msgid="3159291973383796646">"アラーム、リマインダー、予定、指定した人からの着信以外の音やバイブレーションに煩わされることはありません。音楽、動画、ゲームなど再生対象として選択したコンテンツは引き続き再生されます。"</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"アラーム以外の音やバイブレーションに煩わされることはありません。音楽、動画、ゲームなど再生対象として選択したコンテンツは引き続き再生されます。"</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"カスタマイズ"</string>
@@ -469,6 +475,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 低速充電中 • 完了まで <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> • 充電中 • フル充電まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ロック画面のウィジェット"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"左にスワイプすると、コミュニティ チュートリアルが開始します"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"カスタマイズ"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"閉じる"</string>
@@ -554,10 +562,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"今すぐ開始"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"通知はありません"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"新しい通知はありません"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"通知のクールダウンが ON になっています"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"一度に多くの通知が届いたときに、最大 2 分間自動的にデバイスの音量が小さくなりアラートも減ります。"</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"OFF にする"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ロック解除して以前の通知を表示"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"このデバイスは保護者によって管理されています"</string>
@@ -1223,7 +1229,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"認証が必要です。指紋認証センサーをタッチして認証してください。"</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"通話中"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"モバイルデータ"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"接続済み"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"一時的に接続されています"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"接続が不安定です"</string>
@@ -1377,7 +1382,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"完了"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"よくできました。"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"戻る"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"戻るには、3 本の指でタッチパッドを左右にスワイプします。"</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"タッチパッドで 3 本の指を左右に動かしている様子"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"デバイスの画面で「戻る」ジェスチャーのアニメーションが表示されている様子"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"キーボード バックライト"</string>
diff --git a/packages/SystemUI/res/values-ja/tiles_states_strings.xml b/packages/SystemUI/res/values-ja/tiles_states_strings.xml
index 6f85036..790445c 100644
--- a/packages/SystemUI/res/values-ja/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ja/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"OFF"</item>
<item msgid="4875147066469902392">"ON"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"使用不可"</item>
- <item msgid="2004750556637773692">"OFF"</item>
- <item msgid="8968530753931637871">"ON"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"使用不可"</item>
<item msgid="5044688398303285224">"OFF"</item>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index e6b2818..4d0e90c 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"ეფექტურობა"</string>
<string name="user_interface" msgid="3712869377953950887">"სამომხმარებლო ინტერფეისი"</string>
<string name="thermal" msgid="6758074791325414831">"თერმული"</string>
+ <string name="custom" msgid="3337456985275158299">"მორგებული"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"თვალის დევნების მორგებული პარამეტრები"</string>
+ <string name="restore_default" msgid="5259420807486239755">"ნაგულისხმევის აღდგენა"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ცალი ხელის რეჟიმი"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"სმენის აპარატები"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"აქტიური"</string>
@@ -431,6 +434,12 @@
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"პარამეტრები"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"ჩართული"</string>
<string name="zen_mode_off" msgid="1736604456618147306">"გამორთული"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
+ <skip />
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
+ <skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"თქვენ მიერ მითითებული მაღვიძარების, შეხსენებების, მოვლენებისა და ზარების გარდა, არავითარი ხმა და ვიბრაცია არ შეგაწუხებთ. თქვენ მაინც შეძლებთ სასურველი კონტენტის, მაგალითად, მუსიკის, ვიდეოებისა და თამაშების აუდიოს მოსმენა."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"მაღვიძარების გარდა, არავითარი ხმა და ვიბრაცია არ შეგაწუხებთ. თქვენ მაინც შეძლებთ სასურველი კონტენტის, მაგალითად, მუსიკის, ვიდეოებისა და თამაშების აუდიოს მოსმენა."</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"მორგება"</string>
@@ -469,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ნელა იტენება • სრულ დატენვამდე <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> • იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ვიჯეტები ჩაკეტილ ეკრანზე"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"გადაფურცლეთ მარცხნივ, რათა დაიწყოთ საერთო სახელმძღვანელო"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"მორგება"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"უარყოფა"</string>
@@ -554,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"დაწყება ახლავე"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"შეტყობინებები არ არის."</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"ახალი შეტყობინებები არ არის"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"შეტყობინების განტვირთვის პერიოდი ჩართულია"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"მოწყობილობის ხმა და გაფრთხილებები მცირდება 2 წუთის განმავლობაში, როდესაც ბევრ შეტყობინებას მიიღებთ ერთდროულად."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"გამორთვა"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"განბლოკეთ ძველი შეტყობინებების სანახავად"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"მოწყობილობას თქვენი მშობელი მართავს"</string>
@@ -1223,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"საჭიროა ავტორიზაცია. ავტორიზაციისთვის შეეხეთ თითის ანაბეჭდის სენსორს."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"მიმდინარე სატელეფონო ზარი"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"მობილური ინტერნეტი"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"დაკავშირებული"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"დროებით დაკავშირებული"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"სუსტი კავშირი"</string>
@@ -1377,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"მზადაა"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"შესანიშნავია!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"უკან დაბრუნება"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"უკან დასაბრუნებლად, სენსორულ პანელზე ნებისმიერ ადგილას სამი თითის გამოყენებით გადაფურცლეთ მარცხნივ ან მარჯვნივ."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"სენსორული პანელი, რომელიც აჩვენებს მარჯვენა და მარცხენა მიმართულებით მოძრავ სამ თითს"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"მოწყობილობის ეკრანი, რომელიც აჩვენებს უკან დაბრუნების ჟესტის ანიმაციას"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"კლავიატურის შენათება"</string>
diff --git a/packages/SystemUI/res/values-ka/tiles_states_strings.xml b/packages/SystemUI/res/values-ka/tiles_states_strings.xml
index 2b11a15..21f8102 100644
--- a/packages/SystemUI/res/values-ka/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ka/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"გამორთულია"</item>
<item msgid="4875147066469902392">"ჩართულია"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"მიუწვდომელია"</item>
- <item msgid="2004750556637773692">"გამორთული"</item>
- <item msgid="8968530753931637871">"ჩართული"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"მიუწვდომელია"</item>
<item msgid="5044688398303285224">"გამორთულია"</item>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 6415aa1..9d84c73 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Өнімділік"</string>
<string name="user_interface" msgid="3712869377953950887">"Пайдаланушы интерфейсі"</string>
<string name="thermal" msgid="6758074791325414831">"Термовизия"</string>
+ <string name="custom" msgid="3337456985275158299">"Басқа"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Басқа трассалау параметрлері"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Әдепкі қалпына келтіру"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Бір қолмен басқару режимі"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Есту құрылғылары"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Қосулы"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Басымдық режимдері"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Дайын"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Параметрлер"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Қосулы"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Өшірулі"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Оятқыш, еске салғыш, іс-шара мен өзіңіз көрсеткен контактілердің қоңырауларынан басқа дыбыстар мен дірілдер мазаламайтын болады. Музыка, бейне және ойын сияқты медиафайлдарды қоссаңыз, оларды естисіз."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Дабылдардан басқа ешқандай дыбыстар мен дірілдер мазаламайтын болады. Музыка, бейне және ойындар сияқты ойнатылатын контентті ести алатын боласыз."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Баяу зарядталуда • Толуына <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> • Зарядталып жатыр. • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Құлыптаулы экрандағы виджеттер"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Ортақ оқулықты ашу үшін солға қарай сырғытыңыз."</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Бейімдеу"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Жабу"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"таңдалған виджетті орналастыру"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Құлып экранының виджеттері"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Планшет құлыпталып тұрса да, құлып экранындағы виджеттерді кез келген адам көре алады."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"виджетті таңдаудан алу"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Құлып экранының виджеттері"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Қолданбаны виджет көмегімен ашу үшін жеке басыңызды растауыңыз керек. Сондай-ақ басқалар оларды планшетіңіз құлыптаулы кезде де көре алатынын ескеріңіз. Кейбір виджеттер құлып экранына арналмаған болады, сондықтан оларды мұнда қосу қауіпсіз болмауы мүмкін."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Түсінікті"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Қазір бастау"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Хабарландырулар жоқ"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Жаңа хабарландырулар жоқ"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Хабарландыру дыбысын азайту параметрі қосулы"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Бір уақытта тым көп хабарландыру келсе, дыбыс деңгейі автоматты түрде азайтылып, хабарландырулар 2 минутқа кідіртіледі."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Өшіру"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Ескі хабарландырулар үшін құлыпты ашыңыз"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Бұл құрылғыны ата-анаңыз басқарады."</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Аутентификациядан өту қажет. Ол үшін саусақ ізін оқу сканерін түртіңіз."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Телефон қоңырауы бар"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобильдік интернет"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Жалғанды"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Уақытша байланыс орнатылды."</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Байланыс нашар."</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Дайын"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Жарайсыз!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Артқа"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Артқа қайту үшін сенсорлық тақтаның кез келген жерінен үш саусақпен солға немесе оңға сырғытыңыз."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Оңға және солға жылжитын үш саусақты көрсетіп тұрған сенсорлық тақта."</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Артқа қайту қимылын көрсетіп тұрған құрылғы экраны."</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Пернетақта жарығы"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Үй басқару элементтері"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Үй басқару элементтерін скринсейверден қолданыңыз."</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Қайтару"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Сенсорлық тақтада үш саусақпен солға не оңға сырғытсаңыз, артқа қайтасыз."</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Сенсорлық сақтада үш саусақпен жоғары сырғытсаңыз, негізгі бетке өтесіз."</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Сенсорлық тақтада үш саусақпен жоғары сырғытып, басып тұрсаңыз, соңғы ашылған қолданбаларды көресіз."</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Пернетақтада әрекет пернесін басып, барлық қолданбаны көре аласыз."</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Артқа қайту үшін сенсорлық тақтаны қолданыңыз"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Үш саусақпен солға не оңға сырғытыңыз. Басқа қимылдарды үйрену үшін түртіңіз."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Негізгі бетке өту үшін сенсорлық тақтаны қолданыңыз"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Үш саусақпен жоғары сырғытыңыз. Басқа қимылдарды үйрену үшін түртіңіз."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Соңғы ашылған қолданбаларды көру үшін сенсорлық тақтаны қолданыңыз"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Үш саусақпен жоғары сырғытып, басып тұрыңыз. Басқа қимылдарды үйрену үшін түртіңіз."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Барлық қолданбаны көру үшін пернетақтаны қолданыңыз"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Әрекет пернесін кез келген уақытта баса аласыз. Басқа қимылдарды үйрену үшін түртіңіз."</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk/tiles_states_strings.xml b/packages/SystemUI/res/values-kk/tiles_states_strings.xml
index 94a9806..cf3aa69 100644
--- a/packages/SystemUI/res/values-kk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-kk/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Өшірулі"</item>
<item msgid="4875147066469902392">"Қосулы"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Қолжетімді емес"</item>
- <item msgid="2004750556637773692">"Өшірулі"</item>
- <item msgid="8968530753931637871">"Қосулы"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Қолжетімсіз"</item>
<item msgid="5044688398303285224">"Өшірулі"</item>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index a85e4b5..b84b6b6 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"ប្រតិបត្តិការ"</string>
<string name="user_interface" msgid="3712869377953950887">"ផ្ទៃប៉ះ"</string>
<string name="thermal" msgid="6758074791325414831">"កម្ដៅ"</string>
+ <string name="custom" msgid="3337456985275158299">"ផ្ទាល់ខ្លួន"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"ការកំណត់ដានផ្ទាល់ខ្លួន"</string>
+ <string name="restore_default" msgid="5259420807486239755">"ស្ដារទៅលំនាំដើម"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"មុខងារប្រើដៃម្ខាង"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ឧបករណ៍ជំនួយការស្ដាប់"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"សកម្ម"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"មុខងារអាទិភាព"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"រួចរាល់"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ការកំណត់"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"បើក"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"បិទ"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"សំឡេង និងរំញ័រនឹងមិនរំខានដល់អ្នកឡើយ លើកលែងតែម៉ោងរោទ៍ ការរំលឹក ព្រឹត្តិការណ៍ និងអ្នកហៅទូរសព្ទដែលអ្នកបញ្ជាក់ប៉ុណ្ណោះ។ អ្នកនឹងនៅតែឮសំឡេងសកម្មភាពគ្រប់យ៉ាងដែលអ្នកលេងដដែល រួមទាំងតន្រ្តី វីដេអូ និងហ្គេម។"</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"សំឡេង និងរំញ័រនឹងមិនរំខានដល់អ្នកឡើយ លើកលែងតែម៉ោងរោទ៍ប៉ុណ្ណោះ។ អ្នកនឹងនៅតែឮសំឡេងសកម្មភាពគ្រប់យ៉ាងដែលអ្នកលេងដដែល រួមទាំងតន្រ្តី វីដេអូ និងហ្គេម។"</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុងសាកថ្មយឺត • ពេញក្នុងរយៈពេល <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> • កំពុងសាកថ្ម • ពេញក្នុងរយៈពេល <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ធាតុក្រាហ្វិកនៅលើអេក្រង់ចាក់សោ"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"អូសទៅឆ្វេង ដើម្បីចាប់ផ្ដើមមេរៀនសហគមន៍"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ប្ដូរតាមបំណង"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ច្រានចោល"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"ដាក់ធាតុក្រាហ្វិកដែលបានជ្រើសរើស"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"ធាតុក្រាហ្វិកអេក្រង់ចាក់សោ"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"អ្នកគ្រប់គ្នាអាចមើលធាតុក្រាហ្វិកលើអេក្រង់ចាក់សោរបស់អ្នក ទោះបីជាថេប្លេតរបស់អ្នកត្រូវបានចាក់សោក៏ដោយ។"</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ដកការជ្រើសរើសធាតុក្រាហ្វិក"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ធាតុក្រាហ្វិកលើអេក្រង់ចាក់សោ"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ដើម្បីបើកកម្មវិធីដោយប្រើធាតុក្រាហ្វិក អ្នកនឹងត្រូវផ្ទៀងផ្ទាត់ថាជាអ្នក។ ទន្ទឹមនឹងនេះ សូមចងចាំថា នរណាក៏អាចមើលធាតុក្រាហ្វិកបាន សូម្បីពេលថេប្លេតរបស់អ្នកជាប់សោក៏ដោយ។ ធាតុក្រាហ្វិកមួយចំនួនប្រហែលមិនត្រូវបានរចនាឡើងសម្រាប់អេក្រង់ចាក់សោរបស់អ្នកទេ និងមិនមានសុវត្ថិភាពឡើយ បើបញ្ចូលទៅទីនេះ។"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"យល់ហើយ"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"ចាប់ផ្ដើមឥឡូវ"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"គ្មានការជូនដំណឹង"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"គ្មានការជូនដំណឹងថ្មីៗទេ"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"ការបន្ថយសំឡេងការជូនដំណឹងត្រូវបានបើក"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"កម្រិតសំឡេង និងការជូនដំណឹងនៅលើឧបករណ៍របស់អ្នកត្រូវបានកាត់បន្ថយដោយស្វ័យប្រវត្តិរហូតដល់ 2 នាទី នៅពេលអ្នកទទួលបានការជូនដំណឹងច្រើនពេកក្នុងពេលតែមួយ។"</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"បិទ"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ដោះសោដើម្បីមើលការជូនដំណឹងចាស់ៗ"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ឧបករណ៍នេះស្ថិតក្រោមការគ្រប់គ្រងរបស់មាតាបិតាអ្នក"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"តម្រូវឱ្យមានការផ្ទៀងផ្ទាត់។ សូមចុចឧបករណ៍ចាប់ស្នាមម្រាមដៃ ដើម្បីផ្ទៀងផ្ទាត់។"</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ការហៅទូរសព្ទដែលកំពុងដំណើរការ"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"ទិន្នន័យទូរសព្ទចល័ត"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"បានភ្ជាប់"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"បានភ្ជាប់ជាបណ្ដោះអាសន្ន"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"ការតភ្ជាប់ខ្សោយ"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"រួចរាល់"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ធ្វើបានល្អ!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ថយក្រោយ"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"ដើម្បីថយក្រោយ សូមអូសទៅឆ្វេង ឬស្ដាំដោយប្រើម្រាមដៃបីនៅកន្លែងណាមួយនៅលើផ្ទាំងប៉ះ។"</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ផ្ទាំងប៉ះដែលបង្ហាញម្រាមដៃបីដែលផ្លាស់ទីទៅស្ដាំ និងឆ្វេង"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"អេក្រង់ឧបករណ៍ដែលបង្ហាញរូបមានចលនាសម្រាប់ចលនាថយក្រោយ"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ពន្លឺក្រោយក្ដារចុច"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"ការគ្រប់គ្រងផ្ទះ"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"ចូលប្រើការគ្រប់គ្រងផ្ទះអ្នកបានលឿនជាធាតុរក្សាអេក្រង់"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"ត្រឡប់វិញ"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"ដើម្បីថយក្រោយ សូមអូសទៅឆ្វេង ឬស្ដាំដោយប្រើម្រាមដៃបីនៅលើផ្ទាំងប៉ះ"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"ដើម្បីចូលទៅទំព័រដើម សូមអូសឡើងលើដោយប្រើម្រាមដៃបីនៅលើផ្ទាំងប៉ះ"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"ដើម្បីមើលកម្មវិធីថ្មីៗ សូមអូសឡើងលើ ហើយសង្កត់ឱ្យជាប់ដោយប្រើម្រាមដៃបីនៅលើផ្ទាំងប៉ះ"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ដើម្បីមើលកម្មវិធីទាំងអស់របស់អ្នក សូមចុចគ្រាប់ចុចសកម្មភាពនៅលើក្ដារចុចរបស់អ្នក"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"ប្រើផ្ទាំងប៉ះរបស់អ្នក ដើម្បីថយក្រោយ"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"អូសទៅឆ្វេង ឬស្ដាំដោយប្រើម្រាមដៃបី។ ចុច ដើម្បីស្វែងយល់បន្ថែមអំពីចលនា។"</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"ប្រើផ្ទាំងប៉ះរបស់អ្នក ដើម្បីចូលទៅទំព័រដើម"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"អូសឡើងលើដោយប្រើម្រាមដៃបី។ ចុច ដើម្បីស្វែងយល់បន្ថែមអំពីចលនា។"</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"ប្រើផ្ទាំងប៉ះរបស់អ្នក ដើម្បីមើលកម្មវិធីថ្មីៗ"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"អូសឡើងលើ ហើយសង្កត់ឱ្យជាប់ដោយប្រើម្រាមដៃបី។ ចុច ដើម្បីស្វែងយល់បន្ថែមអំពីចលនា។"</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"ប្រើក្ដារចុចរបស់អ្នក ដើម្បីមើលកម្មវិធីទាំងអស់"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ចុចគ្រាប់ចុចសកម្មភាពនៅពេលណាក៏បាន។ ចុច ដើម្បីស្វែងយល់បន្ថែមអំពីចលនា។"</string>
</resources>
diff --git a/packages/SystemUI/res/values-km/tiles_states_strings.xml b/packages/SystemUI/res/values-km/tiles_states_strings.xml
index 11e2c2a..54790f6 100644
--- a/packages/SystemUI/res/values-km/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-km/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"បិទ"</item>
<item msgid="4875147066469902392">"បើក"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"មិនមានទេ"</item>
- <item msgid="2004750556637773692">"បិទ"</item>
- <item msgid="8968530753931637871">"បើក"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"មិនមានទេ"</item>
<item msgid="5044688398303285224">"បិទ"</item>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 670ba04..8ad74af 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"ಪರ್ಫಾರ್ಮೆನ್ಸ್"</string>
<string name="user_interface" msgid="3712869377953950887">"ಬಳಕೆದಾರ ಇಂಟರ್ಫೇಸ್"</string>
<string name="thermal" msgid="6758074791325414831">"ಥರ್ಮಲ್"</string>
+ <string name="custom" msgid="3337456985275158299">"ಕಸ್ಟಮ್"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"ಕಸ್ಟಮ್ ಜಾಡಿನ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
+ <string name="restore_default" msgid="5259420807486239755">"ಡೀಫಾಲ್ಟ್ ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಿ"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ಒಂದು ಕೈ ಮೋಡ್"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ಶ್ರವಣ ಸಾಧನಗಳು"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"ಸಕ್ರಿಯವಾಗಿದೆ"</string>
@@ -431,6 +434,12 @@
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"ಆನ್ ಆಗಿದೆ"</string>
<string name="zen_mode_off" msgid="1736604456618147306">"ಆಫ್ ಆಗಿದೆ"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
+ <skip />
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
+ <skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"ಅಲಾರಾಂಗಳು, ಜ್ಞಾಪನೆಗಳು, ಈವೆಂಟ್ಗಳು ಹಾಗೂ ನೀವು ಸೂಚಿಸಿರುವ ಕರೆದಾರರನ್ನು ಹೊರತುಪಡಿಸಿ ಬೇರಾವುದೇ ಸದ್ದುಗಳು ಅಥವಾ ವೈಬ್ರೇಶನ್ಗಳು ನಿಮಗೆ ತೊಂದರೆ ನೀಡುವುದಿಲ್ಲ. ಹಾಗಿದ್ದರೂ, ನೀವು ಪ್ಲೇ ಮಾಡುವ ಸಂಗೀತ, ವೀಡಿಯೊಗಳು ಮತ್ತು ಆಟಗಳ ಆಡಿಯೊವನ್ನು ನೀವು ಕೇಳಿಸಿಕೊಳ್ಳುತ್ತೀರಿ."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"ಅಲಾರಾಂಗಳನ್ನು ಹೊರತುಪಡಿಸಿ, ಬೇರಾವುದೇ ಸದ್ದುಗಳು ಅಥವಾ ವೈಬ್ರೇಶನ್ಗಳು ನಿಮಗೆ ತೊಂದರೆ ನೀಡುವುದಿಲ್ಲ. ಹಾಗಿದ್ದರೂ, ನೀವು ಪ್ಲೇ ಮಾಡುವ ಸಂಗೀತ, ವೀಡಿಯೊಗಳು ಮತ್ತು ಆಟಗಳ ಆಡಿಯೊವನ್ನು ಕೇಳಿಸಿಕೊಳ್ಳುತ್ತೀರಿ."</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"ಕಸ್ಟಮೈಸ್ ಮಾಡು"</string>
@@ -469,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ನಿಧಾನವಾಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <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> • ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ಲಾಕ್ ಸ್ಕ್ರೀನ್ನಲ್ಲಿ ವಿಜೆಟ್ಗಳು"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ಸಮುದಾಯದ ಟ್ಯುಟೋರಿಯಲ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸಲು ಎಡಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ಕಸ್ಟಮೈಸ್ ಮಾಡಿ"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ವಜಾಗೊಳಿಸಿ"</string>
@@ -554,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"ಈಗ ಪ್ರಾರಂಭಿಸಿ"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"ಯಾವುದೇ ಅಧಿಸೂಚನೆಗಳಿಲ್ಲ"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"ಯಾವುದೇ ಹೊಸ ಅಧಿಸೂಚನೆಗಳಿಲ್ಲ"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"ನೋಟಿಫಿಕೇಶನ್ ಕೂಲ್ಡೌನ್ ಆನ್ ಆಗಿದೆ"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"ನೀವು ಏಕಕಾಲದಲ್ಲಿ ತೀರಾ ಹೆಚ್ಚು ನೋಟಿಫಿಕೇಶನ್ಗಳನ್ನು ಪಡೆದಾಗ 2 ನಿಮಿಷಗಳವರೆಗೆ ನಿಮ್ಮ ಸಾಧನದ ವಾಲ್ಯೂಮ್ ಮತ್ತು ಅಲರ್ಟ್ಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಕಡಿಮೆ ಮಾಡಲಾಗುತ್ತದೆ."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"ಆಫ್ ಮಾಡಿ"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ಹಳೆಯ ಅಧಿಸೂಚನೆಗಳನ್ನು ನೋಡಲು ಅನ್ಲಾಕ್ ಮಾಡಿ"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ಈ ಸಾಧನವನ್ನು ನಿಮ್ಮ ಪೋಷಕರು ನಿರ್ವಹಿಸುತ್ತಿದ್ದಾರೆ"</string>
@@ -1223,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ದೃಢೀಕರಣದ ಅವಶ್ಯಕತೆಯಿದೆ. ದೃಢೀಕರಿಸಲು ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಅನ್ನು ಸ್ಪರ್ಶಿಸಿ."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ಚಾಲ್ತಿಯಲ್ಲಿರುವ ಫೋನ್ ಕರೆ"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"ಮೊಬೈಲ್ ಡೇಟಾ"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ತಾತ್ಕಾಲಿಕವಾಗಿ ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"ಕಳಪೆ ಸಂಪರ್ಕ"</string>
@@ -1377,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ಮುಗಿದಿದೆ"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ಭೇಷ್!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ಹಿಂತಿರುಗಿ"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"ಹಿಂತಿರುಗಲು, ಟಚ್ಪ್ಯಾಡ್ನಲ್ಲಿ ಎಲ್ಲಿಯಾದರೂ ಮೂರು ಬೆರಳುಗಳನ್ನು ಬಳಸಿ ಎಡ ಅಥವಾ ಬಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ಮೂರು ಬೆರಳುಗಳು ಬಲಕ್ಕೆ ಮತ್ತು ಎಡಕ್ಕೆ ಚಲಿಸುತ್ತಿರುವುದನ್ನು ತೋರಿಸುತ್ತಿರುವ ಟಚ್ಪ್ಯಾಡ್"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"ಬ್ಯಾಕ್ ಗೆಸ್ಚರ್ಗೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯನಿಮೇಶನ್ ಅನ್ನು ತೋರಿಸುತ್ತಿರುವ ಸಾಧನದ ಸ್ಕ್ರೀನ್"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ಕೀಬೋರ್ಡ್ ಬ್ಯಾಕ್ಲೈಟ್"</string>
diff --git a/packages/SystemUI/res/values-kn/tiles_states_strings.xml b/packages/SystemUI/res/values-kn/tiles_states_strings.xml
index b2a7523..c7cb2b1 100644
--- a/packages/SystemUI/res/values-kn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-kn/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"ಆಫ್"</item>
<item msgid="4875147066469902392">"ಆನ್"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"ಲಭ್ಯವಿಲ್ಲ"</item>
- <item msgid="2004750556637773692">"ಆಫ್ ಆಗಿದೆ"</item>
- <item msgid="8968530753931637871">"ಆನ್ ಆಗಿದೆ"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"ಲಭ್ಯವಿಲ್ಲ"</item>
<item msgid="5044688398303285224">"ಆಫ್"</item>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 32d4cc5..b904fa8 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"성능"</string>
<string name="user_interface" msgid="3712869377953950887">"사용자 인터페이스"</string>
<string name="thermal" msgid="6758074791325414831">"열화상"</string>
+ <string name="custom" msgid="3337456985275158299">"맞춤"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"맞춤 트레이스 설정"</string>
+ <string name="restore_default" msgid="5259420807486239755">"기본값 복원"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"한 손 사용 모드"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"청각 보조 기기"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"활성"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"우선순위 모드"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"완료"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"설정"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"사용"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"사용 안함"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"알람, 알림, 일정 및 지정한 발신자로부터 받은 전화를 제외한 소리와 진동을 끕니다. 음악, 동영상, 게임 등 재생하도록 선택한 소리는 정상적으로 들립니다."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"알람을 제외한 소리와 진동을 끕니다. 음악, 동영상, 게임 등 재생하도록 선택한 소리는 정상적으로 들립니다."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 저속 충전 중 • <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> • 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"잠금 화면의 위젯"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"공동 튜토리얼을 시작하려면 왼쪽으로 스와이프하세요"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"맞춤설정"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"닫기"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"선택한 위젯 배치"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"잠금 화면 위젯"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"태블릿이 잠겨 있어도 누구나 잠금 화면에서 위젯을 볼 수 있습니다."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"위젯 선택 해제"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"잠금 화면 위젯"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"위젯을 사용하여 앱을 열려면 본인 인증을 해야 합니다. 또한 태블릿이 잠겨 있더라도 누구나 볼 수 있다는 점을 유의해야 합니다. 일부 위젯은 잠금 화면에 적합하지 않고 여기에 추가하기에 안전하지 않을 수 있습니다."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"확인"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"시작하기"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"알림 없음"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"새로운 알림 없음"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"알림 쿨다운 사용 중"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"한 번에 너무 많은 알림을 받으면 최대 2분간 자동으로 기기 볼륨이 줄어들고 알림이 최소화됩니다."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"사용 중지"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"잠금 해제하여 이전 알림 보기"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"부모님이 관리하는 기기입니다."</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"인증이 필요합니다. 지문 센서를 터치하여 인증하세요."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"진행 중인 전화 통화"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"모바일 데이터"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"연결됨"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"일시적으로 연결됨"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"연결 상태 나쁨"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"완료"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"아주 좋습니다."</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"뒤로"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"돌아가려면 세 손가락을 사용해 터치패드의 아무 곳이나 왼쪽 또는 오른쪽으로 스와이프합니다."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"터치패드에서 세 손가락을 좌우로 움직이는 모습"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"뒤로 동작 애니메이션을 보여 주는 기기 화면"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"키보드 백라이트"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"홈 컨트롤"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"화면 보호기로 홈 컨트롤에 빠르게 액세스하기"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"실행취소"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"돌아가려면 터치패드에서 세 손가락을 사용해 왼쪽 또는 오른쪽으로 스와이프하세요"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"홈으로 이동하려면 터치패드에서 세 손가락을 사용해 위로 스와이프합니다"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"최근 앱을 보려면 터치패드에서 세 손가락으로 위로 스와이프한 후 잠시 기다리세요"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"모든 앱을 보려면 키보드의 작업 키를 누르세요"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"터치패드를 사용하여 돌아가기"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"세 손가락을 사용해 왼쪽 또는 오른쪽으로 스와이프하세요. 더 많은 동작을 알아보려면 탭하세요."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"터치패드를 사용하여 홈으로 이동"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"세 손가락을 사용해 위로 스와이프하세요. 더 많은 동작을 알아보려면 탭하세요."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"터치패드를 사용하여 최근 앱 보기"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"세 손가락을 사용해 위로 스와이프한 다음 잠시 기다리세요. 더 많은 동작을 알아보려면 탭하세요."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"키보드를 사용하여 모든 앱 보기"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"언제든지 작업 키를 누릅니다. 더 많은 동작을 알아보려면 탭하세요."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/tiles_states_strings.xml b/packages/SystemUI/res/values-ko/tiles_states_strings.xml
index 963ecc7..bc4740d 100644
--- a/packages/SystemUI/res/values-ko/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ko/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"꺼짐"</item>
<item msgid="4875147066469902392">"켜짐"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"사용 불가"</item>
- <item msgid="2004750556637773692">"사용 안 함"</item>
- <item msgid="8968530753931637871">"사용"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"이용 불가"</item>
<item msgid="5044688398303285224">"꺼짐"</item>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index b96732e..7cea137 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Иштин майнаптуулугу"</string>
<string name="user_interface" msgid="3712869377953950887">"Колдонуучунун интерфейси"</string>
<string name="thermal" msgid="6758074791325414831">"Жылуулук"</string>
+ <string name="custom" msgid="3337456985275158299">"Жеке"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Көз салуунун жеке параметрлери"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Демейки параметрди калыбына келтирүү"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Бир кол режими"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Угуу аппараттары"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Иштеп жатат"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Маанилүүлүк режимдери"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Бүттү"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Параметрлер"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Күйүк"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Өчүк"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Ойготкучтардан, эскертүүлөрдөн, жылнаамадагы иш-чараларды эстеткичтерден жана белгиленген байланыштардын чалууларынан тышкары башка үндөр жана дирилдөөлөр тынчыңызды албайт. Бирок ойнотулуп жаткан музыканы, видеолорду жана оюндарды мурдагыдай эле уга бересиз."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Ойготкучтардан башка үндөр жана дирилдөөлөр тынчыңызды албайт. Бирок ойнотулуп жаткан музыканы, видеолорду жана оюндарды мурдагыдай эле уга бересиз."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Жай кубатталууда • Толгонго чейин <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> • Кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Кулпуланган экрандагы виджеттер"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Жалпы үйрөткүчтү иштетүү үчүн солго сүрүңүз"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Ыңгайлаштыруу"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Жабуу"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"тандалган виджетти жайгаштыруу"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Кулпуланган экрандагы виджеттер"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Планшетиңиз кулпуланган болсо да, кулпуланган экраныңыздан виджеттерди бардыгы көрө алат."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"виджетти тандоодон чыгаруу"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Кулпуланган экрандагы виджеттер"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Колдонмону виджет аркылуу ачуу үчүн бул сиз экениңизди ырасташыңыз керек. Аларды планшетиңиз кулпуланып турса да, баары көрө аларын эске алыңыз. Айрым виджеттер кулпуланган экранда колдонууга арналган эмес жана аларды бул жерге кошуу кооптуу болушу мүмкүн."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Түшүндүм"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Азыр баштоо"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Билдирме жок"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Жаңы билдирмелер жок"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Билдирмелердин үнүн басаңдатуу күйүк"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Бир убакта өтө көп билдирмелер келгенде, түзмөктүн үнү жана эскертүүлөрдүн саны 2 мүнөткө азайтылат."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Өчүрүү"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Билдирмелерди көрүү үчүн кулпуну ачыңыз"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Бул түзмөктү ата-энең башкарат"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Аныктыкты текшерүү талап кылынат. Аныктыгын текшерүү үчүн манжа изинин сенсоруна тийип коюңуз."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Учурдагы телефон чалуу"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилдик трафик"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Туташты"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Убактылуу туташып турат"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Байланыш начар"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Бүттү"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Азаматсыз!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Артка кайтуу"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Кайтуу үчүн сенсордук тактанын каалаган жерин үч манжаңыз менен солго же оңго сүрүңүз."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Үч манжанын оңго жана солго жылып жатканы көрсөтүлгөн сенсордук такта"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Артка жаңсоосунун анимациясы көрсөтүлгөн түзмөктүн экраны"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Баскычтоптун жарыгы"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Үйдөгү түзмөктөрдү тескөө"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Үйдөгү түзмөктөрдү көшөгөдөн ыкчам тескеңиз"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Кайтаруу"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Артка кайтуу үчүн сенсордук тактаны үч манжаңыз менен солго же оңго сүрүңүз"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Башкы бетке өтүү үчүн сенсордук тактаны үч манжаңыз менен өйдө сүрүңүз"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Акыркы колдонмолорду көрүү үчүн сенсордук тактаны үч манжаңыз менен өйдө сүрүп, кармап туруңуз"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Бардык колдонмолоруңузду көрүү үчүн баскычтобуңуздагы аракет баскычын басыңыз"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Артка кайтуу үчүн сенсордук тактаны колдонуңуз"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Үч манжаңыз менен солго же оңго сүрүңүз. Башка жаңсоолорду үйрөнүү үчүн таптаңыз."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Башкы бетке өтүү үчүн сенсордук тактаны колдонуңуз"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Үч манжаңыз менен өйдө сүрүңүз. Башка жаңсоолорду үйрөнүү үчүн таптаңыз."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Акыркы колдонмолорду көрүү үчүн сенсордук тактаны колдонуңуз"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Үч манжаңыз менен өйдө сүрүп, кармап туруңуз. Башка жаңсоолорду үйрөнүү үчүн таптаңыз."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Бардык колдонмолорду көрүү үчүн баскычтобуңузду колдонуңуз"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Каалаганда аракет баскычын басыңыз. Башка жаңсоолорду үйрөнүү үчүн таптаңыз."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky/tiles_states_strings.xml b/packages/SystemUI/res/values-ky/tiles_states_strings.xml
index 3ad9b64..694967e 100644
--- a/packages/SystemUI/res/values-ky/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ky/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Өчүк"</item>
<item msgid="4875147066469902392">"Күйүк"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Жеткиликсиз"</item>
- <item msgid="2004750556637773692">"Өчүк"</item>
- <item msgid="8968530753931637871">"Күйүк"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Жеткиликсиз"</item>
<item msgid="5044688398303285224">"Өчүк"</item>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 4f3e82e..2c490ac 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"ປະສິດທິພາບ"</string>
<string name="user_interface" msgid="3712869377953950887">"ສ່ວນຕິດຕໍ່ຜູ້ໃຊ້"</string>
<string name="thermal" msgid="6758074791325414831">"ຄວາມຮ້ອນ"</string>
+ <string name="custom" msgid="3337456985275158299">"ກຳນົດເອງ"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"ການຕັ້ງຄ່າການຕິດຕາມແບບກຳນົດເອງ"</string>
+ <string name="restore_default" msgid="5259420807486239755">"ກູ້ຄືນຄ່າເລີ່ມຕົ້ນ"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ໂໝດມືດຽວ"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ອຸປະກອນຊ່ວຍຟັງ"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"ນຳໃຊ້ຢູ່"</string>
@@ -431,6 +434,12 @@
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ການຕັ້ງຄ່າ"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"ເປີດ"</string>
<string name="zen_mode_off" msgid="1736604456618147306">"ປິດ"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
+ <skip />
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
+ <skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"ທ່ານຈະບໍ່ໄດ້ຮັບການລົບກວນຈາກສຽງ ແລະ ການສັ່ນເຕືອນ, ຍົກເວັ້ນໃນເວລາໂມງປຸກດັງ, ມີການແຈ້ງເຕືອນ ຫຼື ມີສາຍໂທເຂົ້າຈາກຜູ້ໂທທີ່ທ່ານລະບຸໄວ້. ທ່ານອາດຍັງຄົງໄດ້ຍິນຫາກທ່ານເລືອກຫຼິ້ນເພງ, ວິດີໂອ ແລະ ເກມ."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"ທ່ານຈະບໍ່ໄດ້ຮັບການລົບກວນຈາກສຽງ ແລະ ການສັ່ນເຕືອນ, ຍົກເວັ້ນໃນເວລາໂມງປຸກດັງ. ທ່ານອາດຍັງຄົງໄດ້ຍິນຫາກທ່ານເລືອກຫຼິ້ນເພງ, ວິດີໂອ ແລະ ເກມ."</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"ປັບແຕ່ງ"</string>
@@ -469,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກໄຟແບບຊ້າ • ຈະເຕັມໃນອີກ <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> • ກຳລັງສາກໄຟ • ຈະເຕັມໃນອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ວິດເຈັດຢູ່ໜ້າຈໍລັອກ"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ປັດຊ້າຍເພື່ອເລີ່ມບົດແນະນຳສ່ວນກາງ"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ປັບແຕ່ງ"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ປ່ອຍໄປ"</string>
@@ -554,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"ເລີ່ມດຽວນີ້"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"ບໍ່ມີການແຈ້ງເຕືອນ"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"ບໍ່ມີການແຈ້ງເຕືອນໃໝ່"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"ຄູດາວການແຈ້ງເຕືອນເປີດຢູ່"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"ສຽງ ແລະ ແຈ້ງເຕືອນອຸປະກອນຂອງທ່ານຖືກຫຼຸດລົງໂດຍອັດຕະໂນມັດເປັນເວລາເຖິງ 2 ນາທີເມື່ອທ່ານໄດ້ຮັບການແຈ້ງເຕືອນຫຼາຍເກີນໄປໃນຄັ້ງດຽວ."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"ປິດ"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ປົດລັອກເພື່ອເບິ່ງການແຈ້ງເຕືອນເກົ່າ"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ອຸປະກອນນີ້ແມ່ນຈັດການໂດຍພໍ່ແມ່ຂອງທ່ານ"</string>
@@ -1223,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ຕ້ອງພິສູດຢືນຢັນ. ແຕະໃສ່ເຊັນເຊີລາຍນິ້ວມືເພື່ອພິສູດຢືນຢັນ."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ສາຍໂທອອກ"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"ອິນເຕີເນັດມືຖື"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"ເຊື່ອມຕໍ່ແລ້ວ"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ເຊື່ອມຕໍ່ແລ້ວຊົ່ວຄາວ"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"ສັນຍານເຊື່ອມຕໍ່ຊ້າ"</string>
@@ -1377,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ແລ້ວໆ"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ດີຫຼາຍ!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ກັບຄືນ"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"ເພື່ອກັບຄືນ, ໃຫ້ໃຊ້ 3 ນິ້ວປັດຊ້າຍ ຫຼື ຂວາບ່ອນໃດກໍໄດ້ເທິງແຜ່ນສໍາຜັດ."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ແຜ່ນສໍາຜັດສະແດງພາບ 3 ນິ້ວເລື່ອນໄປທາງຂວາ ແລະ ຊ້າຍ"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"ໜ້າຈໍອຸປະກອນສະແດງພາບເຄື່ອນໄຫວຂອງທ່າທາງກັບຄືນ"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ໄຟປຸ່ມແປ້ນພິມ"</string>
diff --git a/packages/SystemUI/res/values-lo/tiles_states_strings.xml b/packages/SystemUI/res/values-lo/tiles_states_strings.xml
index f42e5ce..9386e00 100644
--- a/packages/SystemUI/res/values-lo/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-lo/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"ປິດ"</item>
<item msgid="4875147066469902392">"ເປີດ"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"ບໍ່ພ້ອມນຳໃຊ້"</item>
- <item msgid="2004750556637773692">"ປິດ"</item>
- <item msgid="8968530753931637871">"ເປີດ"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"ບໍ່ສາມາດໃຊ້ໄດ້"</item>
<item msgid="5044688398303285224">"ປິດ"</item>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 2d48ccf..6b97dc9 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Našumas"</string>
<string name="user_interface" msgid="3712869377953950887">"Naudotojo sąsaja"</string>
<string name="thermal" msgid="6758074791325414831">"Šiluminis"</string>
+ <string name="custom" msgid="3337456985275158299">"Tinkinta"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Tinkinti pėdsako nustatymai"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Atkurti numatytuosius nustatymus"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Vienos rankos režimas"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Klausos įrenginiai"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktyvus"</string>
@@ -431,6 +434,12 @@
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Nustatymai"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Įjungta"</string>
<string name="zen_mode_off" msgid="1736604456618147306">"Išjungta"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
+ <skip />
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
+ <skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Jūsų netrikdys garsai ir vibravimas, išskyrus nurodytų signalų, priminimų, įvykių ir skambintojų garsus. Vis tiek girdėsite viską, ką pasirinksite leisti, įskaitant muziką, vaizdo įrašus ir žaidimus."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Jūsų netrikdys garsai ir vibravimas, išskyrus signalus. Vis tiek girdėsite viską, ką pasirinksite leisti, įskaitant muziką, vaizdo įrašus ir žaidimus."</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"Tinkinti"</string>
@@ -469,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lėtai įkraunama • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkrovimo"</string>
<string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Įkraunama • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkrovimo"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Valdikliai užrakinimo ekrane"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Perbraukite kairėn, paleistumėte bendruomenės mokomąją medžiagą"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Tinkinti"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Atsisakyti"</string>
@@ -554,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Pradėti dabar"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Nėra įspėjimų"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Naujų pranešimų nėra"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Pranešimų neaktyvumo laikotarpis įjungtas"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Jūsų įrenginio garsumas ir įspėjimai automatiškai sumažinami iki dviejų minučių, kai iš karto gaunate per daug pranešimų."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Išjungti"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Atrakinę matykite senesnius pranešimus"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Šį įrenginį tvarko vienas iš tavo tėvų"</string>
@@ -1223,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Reikia nustatyti tapatybę. Nustatykite tapatybę palietę kontrolinio kodo jutiklį."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Vykstantis telefono skambutis"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiliojo ryšio duomenys"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Prisijungta"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Laikinai prijungta"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Prastas ryšys"</string>
@@ -1377,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Atlikta"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Puiku!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Grįžti"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Jei norite grįžti, trimis pirštais perbraukite kairėn arba dešinėn bet kurioje jutiklinės dalies vietoje."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Jutiklinė dalis, kurioje rodomi trys dešinėn ir kairėn judantys pirštai"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Įrenginio ekranas, kuriame rodoma grįžimo gesto animacija"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klaviatūros foninis apšvietimas"</string>
diff --git a/packages/SystemUI/res/values-lt/tiles_states_strings.xml b/packages/SystemUI/res/values-lt/tiles_states_strings.xml
index 90d2e8b..c975e7e 100644
--- a/packages/SystemUI/res/values-lt/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-lt/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Išjungta"</item>
<item msgid="4875147066469902392">"Įjungta"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Nepasiekiama"</item>
- <item msgid="2004750556637773692">"Išjungta"</item>
- <item msgid="8968530753931637871">"Įjungta"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Nepasiekiama"</item>
<item msgid="5044688398303285224">"Išjungta"</item>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index c7b1c96..f191a28 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Veiktspēja"</string>
<string name="user_interface" msgid="3712869377953950887">"Lietotāja saskarne"</string>
<string name="thermal" msgid="6758074791325414831">"Ierīces temperatūra"</string>
+ <string name="custom" msgid="3337456985275158299">"Pielāgots"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Pielāgoti izsekošanas iestatījumi"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Atjaunot noklusējuma vērtību"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Vienas rokas režīms"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Dzirdes aparāti"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktīvs"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritātes režīmi"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gatavs"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Iestatījumi"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Ieslēgts"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Izslēgts"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Jūs netraucēs skaņas un vibrācija, izņemot signālus, atgādinājumus, pasākumus un zvanītājus, ko būsiet norādījis. Jūs joprojām dzirdēsiet atskaņošanai izvēlētos vienumus, tostarp mūziku, videoklipus un spēles."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Jūs netraucēs skaņas un vibrācija, izņemot signālus. Jūs joprojām dzirdēsiet atskaņošanai izvēlētos vienumus, tostarp mūziku, videoklipus un spēles."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lēnā uzlāde • Laiks līdz pilnai uzlādei: <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> • Notiek uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Logrīki bloķēšanas ekrānā"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Velciet pa kreisi, lai palaistu kopienas pamācību."</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Pielāgot"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Nerādīt"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"novietot atlasīto logrīku"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Bloķēšanas ekrāna logrīki"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Jebkurš var skatīt logrīkus bloķēšanas ekrānā, pat ja planšetdators ir bloķēts."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"noņemt logrīka atlasi"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Bloķēšanas ekrāna logrīki"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Lai atvērtu lietotni, izmantojot logrīku, jums būs jāapstiprina sava identitāte. Turklāt ņemiet vērā, ka ikviens var skatīt logrīkus, pat ja planšetdators ir bloķēts. Iespējams, daži logrīki nav paredzēti izmantošanai bloķēšanas ekrānā, un var nebūt droši tos šeit pievienot."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Labi"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Sākt tūlīt"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Nav paziņojumu"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Nav jaunu paziņojumu"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Nogaidīšanas periods paziņojumiem ir ieslēgts"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Saņemot par daudz paziņojumu uzreiz, skaļums un brīdinājumi tiek automātiski samazināti līdz 2 min."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Izslēgt"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Atbloķējiet vecāku paziņojumu skatīšanai"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Šo ierīci pārvalda viens no jūsu vecākiem."</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Nepieciešama autentifikācija. Pieskarieties pirksta nospieduma sensoram, lai veiktu autentificēšanu."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Notiekošs tālruņa zvans"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilie dati"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Ir izveidots savienojums"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Īslaicīgi izveidots savienojums"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Vājš savienojums"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gatavs"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Lieliski!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Atpakaļ"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Lai pārietu atpakaļ, ar trim pirkstiem velciet pa kreisi vai pa labi jebkurā vietā uz skārienpaliktņa"</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Attēls ar skārienpaliktni, uz kura trīs pirksti kustas pa labi un pa kreisi"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ierīces ekrāns, kurā redzama animācija ar žestu pāriešanai atpakaļ"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Tastatūras fona apgaismojums"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Mājas kontrolierīces"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Ātra piekļuve mājas kontrolierīcēm ekrānsaudzētājā"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Atsaukt"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Lai atgrieztos, ar trīs pirkstiem velciet pa kreisi vai pa labi jebkurā vietā uz skārienpaliktņa."</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Lai pārietu uz sākuma ekrāna, ar trīs pirkstiem uz skārienpaliktņa velciet augšup."</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Lai skatītu nesenās lietotnes, ar trīs pirkstiem uz skārienpaliktņa velciet augšup un turiet."</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Lai skatītu visas savas lietotnes, tastatūrā nospiediet darbību taustiņu."</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Atgriešanās, izmantojot skārienpaliktni"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Ar trīs pirkstiem velciet pa kreisi vai pa labi. Lai apgūtu citus žestus, pieskarieties šeit."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Pāriešana uz sākuma ekrānu, izmantojot skārienpaliktni"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Ar trīs pirkstiem velciet augšup. Lai apgūtu citus žestus, pieskarieties šeit."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Pēdējo lietotņu skatīšana, izmantojot skārienpaliktni"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Ar trīs pirkstiem velciet augšup un turiet. Lai apgūtu citus žestus, pieskarieties šeit."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Visu lietotņu skatīšana, izmantojot tastatūru"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Jebkurā laikā varat nospiest darbību taustiņu. Lai apgūtu citus žestus, pieskarieties šeit."</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/tiles_states_strings.xml b/packages/SystemUI/res/values-lv/tiles_states_strings.xml
index 4103c0a..c65a1d4 100644
--- a/packages/SystemUI/res/values-lv/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-lv/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Izslēgts"</item>
<item msgid="4875147066469902392">"Ieslēgts"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Nav pieejams"</item>
- <item msgid="2004750556637773692">"Izslēgts"</item>
- <item msgid="8968530753931637871">"Ieslēgts"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Nav pieejams"</item>
<item msgid="5044688398303285224">"Izslēgts"</item>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 052945e..68f9a9d 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Изведба"</string>
<string name="user_interface" msgid="3712869377953950887">"Кориснички интерфејс"</string>
<string name="thermal" msgid="6758074791325414831">"Термално"</string>
+ <string name="custom" msgid="3337456985275158299">"Приспособено"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Приспособени поставки за следење"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Врати на стандардно"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Режим со една рака"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слушни апарати"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Активно"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Приоритетни режими"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Готово"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Поставки"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Вклучено"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Исклучено"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Нема да ве вознемируваат звуци и вибрации, освен од аларми, потсетници, настани и повикувачи што ќе ги наведете. Сѐ уште ќе слушате сѐ што ќе изберете да пуштите, како музика, видеа и игри."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Нема да ве вознемируваат звуци и вибрации, освен од аларми. Сѐ уште ќе слушате сѐ што ќе изберете да пуштите, како музика, видеа и игри."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Се полни бавно • Полна по <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> • Се полни • Полна по <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Виџети на заклучен екран"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Повлечете налево за да го започнете заедничкото упатство"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Приспособете"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Отфрли"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"поставете го избраниот виџет"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Виџети на заклучен екран"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Секој може да гледа виџети на заклучениот екран, дури и ако таблетот е заклучен."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"поништи го изборот на виџетот"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Виџети на заклучен екран"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"За да отворите апликација со помош на виџет, ќе треба да потврдите дека сте вие. Покрај тоа, имајте предвид дека секој може да ги гледа виџетите, дури и кога вашиот таблет е заклучен. Некои виџети можеби не се наменети за вашиот заклучен екран, па можеби не е безбедно да се додадат овде."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Сфатив"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Започни сега"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Нема известувања"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Нема нови известувања"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"„Подискретни известувања“ е вклучена"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Јачината на звукот и известувањата на уредот се намалуваат автоматски до 2 минути кога добивате премногу известувања одеднаш."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Исклучи"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Отклучете за да ги видите старите известувања"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Родителот управува со уредов"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Потребна е проверка. Допрете го сензорот за отпечаток за да автентицирате."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Тековен телефонски повик"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилен интернет"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Поврзано"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Привремено поврзано"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Слаба интернет-врска"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Одлично сторено!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"За да се вратите назад, повлечете налево или надесно со три прста каде било на допирната подлога."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Допирната подлога покажува три прста што се движат десно и лево"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Екранот на уредот покажува анимација за движење назад"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Осветлување на тастатура"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Контроли за домот"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Контролите за домот како штедач на екран"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Врати"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"За да се вратите назад, повлечете налево или надесно со три прста на допирната подлога"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"За да одите на почетниот екран, повлечете нагоре со три прста на допирната подлога"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"За да ги видите скорешните апликации, повлечете нагоре и задржете со три прста на допирната подлога"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Притиснете го копчето за дејство на тастатурата за да ги видите сите апликации"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Користете ја допирната подлога за да се вратите назад"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Повлечете налево или надесно со три прста. Допрете за да научите повеќе движења."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Користете ја допирната подлога за да одите на почетниот екран"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Повлечете нагоре со три прста. Допрете за да научите повеќе движења."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Користете ја допирната подлога за да ги видите скорешните апликации"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Повлечете нагоре и задржете со три прста. Допрете за да научите повеќе движења."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Користете ја тастатурата за да ги видите сите апликации"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Притиснете го копчето за дејство кога сакате. Допрете за да научите повеќе движења."</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk/tiles_states_strings.xml b/packages/SystemUI/res/values-mk/tiles_states_strings.xml
index 5e9f5bd..a8d9695 100644
--- a/packages/SystemUI/res/values-mk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mk/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Исклучено"</item>
<item msgid="4875147066469902392">"Вклучено"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Недостапно"</item>
- <item msgid="2004750556637773692">"Исклучено"</item>
- <item msgid="8968530753931637871">"Вклучено"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Недостапно"</item>
<item msgid="5044688398303285224">"Исклучено"</item>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index b43be14..8711604 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"പ്രകടനം"</string>
<string name="user_interface" msgid="3712869377953950887">"ഉപയോക്തൃ ഇന്റർഫേസ്"</string>
<string name="thermal" msgid="6758074791325414831">"തെർമൽ"</string>
+ <string name="custom" msgid="3337456985275158299">"ഇഷ്ടാനുസൃതം"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"ഇഷ്ടാനുസൃത അടയാള ക്രമീകരണം"</string>
+ <string name="restore_default" msgid="5259420807486239755">"ഡിഫോൾട്ട് പുനഃസ്ഥാപിക്കുക"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ഒറ്റക്കൈ മോഡ്"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"കേൾവിക്കുള്ള ഉപകരണങ്ങൾ"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"സജീവം"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"മുൻഗണനാ മോഡുകൾ"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"ശരി"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ക്രമീകരണം"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"ഓണാണ്"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"ഓഫാണ്"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"നിങ്ങൾ സജ്ജീകരിച്ച അലാറങ്ങൾ, റിമൈൻഡറുകൾ, ഇവന്റുകൾ, കോളർമാർ എന്നിവയിൽ നിന്നുള്ള ശബ്ദങ്ങളും വൈബ്രേഷനുകളുമൊഴികെ മറ്റൊന്നും നിങ്ങളെ ശല്യപ്പെടുത്തുകയില്ല. സംഗീതം, വീഡിയോകൾ, ഗെയിമുകൾ എന്നിവയുൾപ്പെടെ പ്ലേ ചെയ്യുന്നതെന്തും നിങ്ങൾക്ക് തുടർന്നും കേൾക്കാൻ കഴിയും."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"അലാറങ്ങളിൽ നിന്നുള്ള ശബ്ദങ്ങളും വൈബ്രേഷനുകളുമൊഴികെ മറ്റൊന്നും നിങ്ങളെ ശല്യപ്പെടുത്തുകയില്ല. സംഗീതം, വീഡിയോകൾ, ഗെയിമുകൾ എന്നിവയുൾപ്പെടെ പ്ലേ ചെയ്യുന്നതെന്തും നിങ്ങൾക്ക് തുടർന്നും കേൾക്കാൻ കഴിയും."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • പതുക്കെ ചാർജ് ചെയ്യുന്നു • <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> • ചാർജ് ചെയ്യുന്നു • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ലോക്ക് സ്ക്രീനിൽ വിജറ്റുകൾ"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"കമ്മ്യൂണൽ ട്യൂട്ടോറിയൽ ആരംഭിക്കാൻ ഇടത്തോട്ട് സ്വൈപ്പ് ചെയ്യുക"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ഇഷ്ടാനുസൃതമാക്കുക"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ഡിസ്മിസ് ചെയ്യുക"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"തിരഞ്ഞെടുത്ത വിജറ്റ് നൽകുക"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"ലോക്ക് സ്ക്രീൻ വിജറ്റുകൾ"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"ടാബ്ലെറ്റ് ലോക്കാണെങ്കിൽ പോലും ലോക്ക് സ്ക്രീനിൽ ആർക്കും വിജറ്റുകൾ കാണാം."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"വിജറ്റ് തിരഞ്ഞെടുത്തത് മാറ്റുക"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ലോക്ക് സ്ക്രീൻ വിജറ്റുകൾ"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"വിജറ്റ് ഉപയോഗിച്ച് ഒരു ആപ്പ് തുറക്കാൻ, ഇത് നിങ്ങൾ തന്നെയാണെന്ന് പരിശോധിച്ചുറപ്പിക്കേണ്ടതുണ്ട്. നിങ്ങളുടെ ടാബ്ലെറ്റ് ലോക്കായിരിക്കുമ്പോഴും എല്ലാവർക്കും അത് കാണാനാകുമെന്നതും ഓർക്കുക. ചില വിജറ്റുകൾ നിങ്ങളുടെ ലോക്ക് സ്ക്രീനിന് ഉള്ളതായിരിക്കില്ല, അവ ഇവിടെ ചേർക്കുന്നത് സുരക്ഷിതവുമായിരിക്കില്ല."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"മനസ്സിലായി"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"ഇപ്പോൾ ആരംഭിക്കുക"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"അറിയിപ്പുകൾ ഒന്നുമില്ല"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"പുതിയ അറിയിപ്പുകളൊന്നുമില്ല"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"അറിയിപ്പിന്റെ ശബ്ദം കുറയ്ക്കൽ ഓണാണ്"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"നിരവധി അറിയിപ്പ് ഒരുമിച്ച് ലഭിക്കുമ്പോൾ, ഉപകരണത്തിന്റെ ശബ്ദവും മുന്നറിയിപ്പും 2 മിനിറ്റ് വരെ സ്വയമേവ കുറയ്ക്കും."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"ഓഫാക്കുക"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"പഴയ അറിയിപ്പുകൾ കാണാൻ അൺലോക്ക് ചെയ്യുക"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ഈ ഉപകരണം മാനേജ് ചെയ്യുന്നത് നിങ്ങളുടെ രക്ഷിതാവാണ്"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"പരിശോധിച്ചുറപ്പിക്കേണ്ടതുണ്ട്. പരിശോധിച്ചുറപ്പിക്കാൻ, വിരലടയാള സെൻസറിൽ സ്പർശിക്കുക."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"സജീവമായ ഫോൺ കോൾ"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"മൊബൈൽ ഡാറ്റ"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"കണക്റ്റ് ചെയ്തു"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"താൽക്കാലികമായി കണക്റ്റ് ചെയ്തിരിക്കുന്നു"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"ദുർബലമായ കണക്ഷൻ"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"പൂർത്തിയായി"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"കൊള്ളാം!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"മടങ്ങുക"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"തിരികെ പോകാൻ, ടച്ച്പാഡിൽ എവിടെയെങ്കിലും മൂന്ന് വിരലുകൾ ഉപയോഗിച്ച് ഇടത്തേക്കോ വലത്തേക്കോ സ്വൈപ്പ് ചെയ്യുക."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"വലത്തേക്കും ഇടത്തേക്കും ചലിക്കുന്ന മൂന്ന് വിരലുകൾ കാണിക്കുന്ന ടച്ച്പാഡ്"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"ബാക്ക് ജെസ്ച്ചറിനായി ആനിമേഷൻ കാണിക്കുന്ന ഉപകരണ സ്ക്രീൻ"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"കീബോഡ് ബാക്ക്ലൈറ്റ്"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"ഹോം കൺട്രോളുകൾ"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"സ്ക്രീൻസേവറായി ഹോം കൺട്രോളുകൾ പെട്ടെന്ന് ആക്സസ് ചെയ്യൂ"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"പഴയപടിയാക്കുക"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"തിരികെ പോകാൻ, മൂന്ന് വിരലുകൾ ഉപയോഗിച്ച് ടച്ച്പാഡിൽ ഇടത്തേക്കോ വലത്തേക്കോ സ്വൈപ്പ് ചെയ്യുക"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"ഹോമിലേക്ക് പോകാൻ, മൂന്ന് വിരലുകൾ ഉപയോഗിച്ച് ടച്ച്പാഡിൽ മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"അടുത്തിടെ ഉപയോഗിച്ച ആപ്പുകൾ കാണാൻ, മൂന്ന് വിരലുകൾ ഉപയോഗിച്ച് ടച്ച്പാഡിൽ സ്വൈപ്പ് ചെയ്ത് പിടിക്കുക"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"എല്ലാ ആപ്പുകളും കാണാൻ, നിങ്ങളുടെ കീബോർഡിലെ ആക്ഷൻ കീ അമർത്തുക"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"തിരികെ പോകാൻ നിങ്ങളുടെ ടച്ച്പാഡ് ഉപയോഗിക്കുക"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"മൂന്ന് വിരലുകളാൽ ഇടത്തേക്കോ വലത്തേക്കോ സ്വൈപ്പുചെയ്യൂ. കൂടുതൽ ജെസ്ച്ചറുകൾ മനസ്സിലാക്കാൻ ടാപ്പ് ചെയ്യുക."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"ഹോമിലേക്ക് പോകാൻ നിങ്ങളുടെ ടച്ച്പാഡ് ഉപയോഗിക്കുക"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"മൂന്ന് വിരലുകൾ കൊണ്ട് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക. കൂടുതൽ ജെസ്ച്ചറുകൾ മനസ്സിലാക്കാൻ ടാപ്പ് ചെയ്യുക."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"അടുത്തിടെ ഉപയോഗിച്ച ആപ്പുകൾ കാണാൻ നിങ്ങളുടെ ടച്ച്പാഡ് ഉപയോഗിക്കുക"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"മൂന്ന് വിരലുകൾ കൊണ്ട് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്ത് പിടിക്കുക. കൂടുതൽ ജെസ്ച്ചറുകൾ മനസ്സിലാക്കാൻ ടാപ്പ് ചെയ്യുക."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"എല്ലാ ആപ്പുകളും കാണാൻ നിങ്ങളുടെ കീബോർഡ് ഉപയോഗിക്കുക"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ഏതുസമയത്തും ആക്ഷൻ കീ അമർത്തുക. കൂടുതൽ ജെസ്ച്ചറുകൾ മനസ്സിലാക്കാൻ ടാപ്പ് ചെയ്യുക."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml/tiles_states_strings.xml b/packages/SystemUI/res/values-ml/tiles_states_strings.xml
index 6b4e937..609fdde 100644
--- a/packages/SystemUI/res/values-ml/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ml/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"ഓഫാണ്"</item>
<item msgid="4875147066469902392">"ഓണാണ്"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"ലഭ്യമല്ല"</item>
- <item msgid="2004750556637773692">"ഓഫാണ്"</item>
- <item msgid="8968530753931637871">"ഓണാണ്"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"ലഭ്യമല്ല"</item>
<item msgid="5044688398303285224">"ഓഫാണ്"</item>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 6736288..95b4e3f 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -131,7 +131,7 @@
<string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Та одоогоор <xliff:g id="APP_NAME">%1$s</xliff:g>-г бичиж байна"</string>
<string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Бичихийг зогсоох"</string>
<string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"Дэлгэцийг хуваалцаж байна"</string>
- <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Дэлгэцийг хуваалцахыг зогсоох уу?"</string>
+ <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Дэлгэц хуваалцахыг зогсоох уу?"</string>
<string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Та одоогоор дэлгэцээ бүтнээр нь <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>-тай хуваалцаж байна"</string>
<string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Та одоогоор дэлгэцээ бүтнээр нь нэг апптай хуваалцаж байна"</string>
<string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Та одоогоор <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>-г хуваалцаж байна"</string>
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Гүйцэтгэл"</string>
<string name="user_interface" msgid="3712869377953950887">"Хэрэглэгчийн интерфейс"</string>
<string name="thermal" msgid="6758074791325414831">"Дулааны"</string>
+ <string name="custom" msgid="3337456985275158299">"Захиалгат"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Захиалгат ул мөрийн тохиргоо"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Өгөгдмөлийг сэргээх"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Нэг гарын горим"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Сонсголын төхөөрөмжүүд"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Идэвхтэй"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Чухал байдлаар нь ангилах горим"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Болсон"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Тохиргоо"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Асаалттай"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Унтраалттай"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Танд сэрүүлэг, сануулга, арга хэмжээ, таны сонгосон дуудлага илгээгчээс бусад дуу, чичиргээ саад болохгүй. Та хөгжим, видео, тоглоом зэрэг тоглуулахыг хүссэн бүх зүйлээ сонсох боломжтой хэвээр байна."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Танд сэрүүлгээс бусад дуу, чичиргээ саад болохгүй. Та хөгжим, видео, тоглоом зэрэг тоглуулахыг хүссэн бүх зүйлээ сонсох боломжтой хэвээр байна."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Удаан цэнэглэж байна • <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> • Цэнэглэж байна • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-н дараа дүүрнэ"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Түгжээтэй дэлгэц дээрх виджетүүд"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Нийтийн практик хичээлийг эхлүүлэхийн тулд зүүн тийш шударна уу"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Өөрчлөх"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Хаах"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"сонгосон виджетийг байрлуулах"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Түгжээтэй дэлгэцийн виджет"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Таны таблет түгжээтэй байсан ч түгжээтэй дэлгэцийн виджетийг тань дурын хүн үзнэ"</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"виджетийн сонголтыг болиулах"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Түгжээтэй дэлгэцийн виджет"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Виджет ашиглан аппыг нээхийн тулд та өөрийгөө мөн болохыг баталгаажуулах шаардлагатай болно. Мөн таны таблет түгжээтэй байсан ч тэдгээрийг дурын хүн үзэж болохыг санаарай. Зарим виджет таны түгжээтэй дэлгэцэд зориулагдаагүй байж магадгүй ба энд нэмэхэд аюултай байж болзошгүй."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Ойлголоо"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Одоо эхлүүлэх"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Мэдэгдэл байхгүй"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Шинэ мэдэгдэл алга"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Мэдэгдлийн хөргөлт асаалттай байна"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Таныг хэт олон мэдэгдэл нэг дор авахад таны төхөөрөмжийн дууны түвшин болон сэрэмжлүүлэг/дохиог 2 хүртэлх минутын турш автоматаар багасгадаг."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Унтраах"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Хуучин мэдэгдлийг харах бол түгжээг тайл"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Энэ төхөөрөмжийг таны эцэг эх удирддаг"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Баталгаажуулалт шаардлагатай. Баталгаажуулахын тулд хурууны хээ мэдрэгчид хүрнэ үү."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Үргэлжилж буй утасны дуудлага"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобайл дата"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Холбогдсон"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Түр зуур холбогдсон"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Холболт сул байна"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Болсон"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Үнэхээр сайн ажиллалаа!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Буцах"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Буцаж очихын тулд мэдрэгч самбар дээр гурван хуруугаараа хүссэн газраа зүүн эсвэл баруун тийш шударна уу."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Гурван хуруу баруун болон зүүн тийш хөдөлж буйг харуулсан мэдрэгч самбар"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Буцах зангаанд зориулсан анимацийг харуулсан төхөөрөмжийн дэлгэц"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Гарын арын гэрэл"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Гэрийн удирдлага"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Гэрийн удирдлагадаа дэлгэц амраагчаар шуурхай ханд"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Болих"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Буцахын тулд мэдрэгч самбар дээр гурван хуруугаараа зүүн эсвэл баруун тийш шударна уу"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Нүүр хуудас руу очихын тулд мэдрэгч самбар дээр гурван хуруугаараа дээш шударна уу"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Саяхны аппуудыг харахын тулд мэдрэгч самбар дээр гурван хуруугаараа дээш шудраад, удаан дарна уу"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Бүх аппаа харахын тулд гар дээр тань байх тусгай товчлуурыг дарна уу"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Буцахын тулд мэдрэгч самбараа ашиглах"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Гурван хуруугаараа зүүн эсвэл баруун тийш шударна уу. Илүү олон зангаа сурахын тулд товшино уу."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Нүүр хуудас руу очихын тулд мэдрэгч самбараа ашиглах"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Гурван хуруугаа ашиглан дээш шударна уу. Илүү олон зангаа сурахын тулд товшино уу."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Саяхны аппуудыг харахын тулд мэдрэгч самбараа ашиглах"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Гурван хуруугаа ашиглан дээш шудраад, удаан дарна уу. Илүү олон зангаа сурахын тулд товшино уу."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Бүх аппыг харахын тулд гараа ашиглах"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Тусгай товчлуурыг хүссэн үедээ дарна уу. Илүү олон зангаа сурахын тулд товшино уу."</string>
</resources>
diff --git a/packages/SystemUI/res/values-mn/tiles_states_strings.xml b/packages/SystemUI/res/values-mn/tiles_states_strings.xml
index 5a32c09..a3f5454 100644
--- a/packages/SystemUI/res/values-mn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mn/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Унтраалттай"</item>
<item msgid="4875147066469902392">"Асаалттай"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Боломжгүй"</item>
- <item msgid="2004750556637773692">"Унтраалттай"</item>
- <item msgid="8968530753931637871">"Асаалттай"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Боломжгүй"</item>
<item msgid="5044688398303285224">"Унтраалттай"</item>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 245b42f..e3510ad 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"परफॉर्मन्स"</string>
<string name="user_interface" msgid="3712869377953950887">"यूझर इंटरफेस"</string>
<string name="thermal" msgid="6758074791325414831">"थर्मल"</string>
+ <string name="custom" msgid="3337456985275158299">"कस्टम"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"मागाच्या कस्टम सेटिंग्ज"</string>
+ <string name="restore_default" msgid="5259420807486239755">"डीफॉल्ट रिस्टोअर करा"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"एकहाती मोड"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"श्रवणयंत्रे"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"ॲक्टिव्ह आहे"</string>
@@ -431,6 +434,12 @@
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"सेटिंग्ज"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"सुरू आहे"</string>
<string name="zen_mode_off" msgid="1736604456618147306">"बंद आहे"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
+ <skip />
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
+ <skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"अलार्म, रिमाइंडर, इव्हेंट आणि तुम्ही निश्चित केलेल्या कॉलर व्यतिरिक्त तुम्हाला कोणत्याही आवाज आणि कंपनांचा व्यत्त्यय आणला जाणार नाही. तरीही तुम्ही प्ले करायचे ठरवलेले कोणतेही संगीत, व्हिडिओ आणि गेमचे आवाज ऐकू शकतात."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"अलार्म व्यतिरिक्त तुम्हाला कोणत्याही आवाज आणि कंपनांचा व्यत्त्यय आणला जाणार नाही. तरीही तुम्ही प्ले करायचे ठरवलेले कोणतेही संगीत, व्हिडिओ आणि गेमचे आवाज ऐकू शकतात."</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"सानुकूलित करा"</string>
@@ -469,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • हळू चार्ज होत आहे • <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> • चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"लॉक स्क्रीनवरील विजेट"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"सामुदायिक ट्यूटोरियल सुरू करण्यासाठी डावीकडे स्वाइप करा"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"कस्टमाइझ करा"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"डिसमिस करा"</string>
@@ -554,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"आता सुरू करा"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"सूचना नाहीत"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"नवीन सूचना नाहीत"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"नोटिफिकेशन कूलडाउन सुरू आहे"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"एकाच वेळी अनेक नोटिफिकेशन मिळाल्यास, डिव्हाइसचा आवाज आणि सूचना आपोआप कमाल २ मिनिटांपर्यंत कमी होतात."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"बंद करा"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"जुन्या सूचना पाहण्यासाठी अनलॉक करा"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"हे डिव्हाइस तुमच्या पालकाने व्यवस्थापित केले आहे"</string>
@@ -1223,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ऑथेंटिकेशन आवश्यक आहे. ऑथेंटिकेट करण्यासाठी फिंगरप्रिंट सेन्सरला स्पर्श करा."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"फोन कॉल सुरू आहे"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"कनेक्ट केले आहे"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"तात्पुरते कनेक्ट केलेले"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"खराब कनेक्शन"</string>
@@ -1377,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"पूर्ण झाले"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"उत्तम कामगिरी!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"मागे जा"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"मागे जाण्यासाठी, टचपॅडवर कुठेही तीन बोटांनी डावीकडे किंवा उजवीकडे स्वाइप करा."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"तीन बोट उजवीकडे आणि डावीकडे हलताना दाखवणारे टचपॅड"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"मागील जेश्चरसाठी अॅनिमेशन दाखवणारी डिव्हाइस स्क्रीन"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"कीबोर्ड बॅकलाइट"</string>
diff --git a/packages/SystemUI/res/values-mr/tiles_states_strings.xml b/packages/SystemUI/res/values-mr/tiles_states_strings.xml
index fdb1f40..54c320c 100644
--- a/packages/SystemUI/res/values-mr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mr/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"बंद आहे"</item>
<item msgid="4875147066469902392">"सुरू आहे"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"उपलब्ध नाही"</item>
- <item msgid="2004750556637773692">"बंद आहे"</item>
- <item msgid="8968530753931637871">"सुरू आहे"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"उपलब्ध नाही"</item>
<item msgid="5044688398303285224">"बंद आहे"</item>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index bca5272..0e91cb4 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Prestasi"</string>
<string name="user_interface" msgid="3712869377953950887">"Antara Muka Pengguna"</string>
<string name="thermal" msgid="6758074791325414831">"Terma"</string>
+ <string name="custom" msgid="3337456985275158299">"Tersuai"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Tetapan Surih Tersuai"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Pemulihan Lalai"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Mod sebelah tangan"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Peranti pendengaran"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktif"</string>
@@ -431,6 +434,9 @@
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Tetapan"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Hidup"</string>
<string name="zen_mode_off" msgid="1736604456618147306">"Mati"</string>
+ <string name="zen_mode_set_up" msgid="7457957033034460064">"Sediakan"</string>
+ <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Urus dalam tetapan"</string>
+ <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Tiada mod yang aktif}=1{{mode} aktif}other{# mod aktif}}"</string>
<string name="zen_priority_introduction" msgid="3159291973383796646">"Anda tidak akan diganggu oleh bunyi dan getaran, kecuali daripada penggera, peringatan, acara dan pemanggil yang anda tetapkan. Anda masih mendengar item lain yang anda pilih untuk dimainkan termasuk muzik, video dan permainan."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Anda tidak akan diganggu oleh bunyi dan getaran, kecuali daripada penggera. Anda masih mendengar item lain yang anda pilih untuk dimainkan termasuk muzik, video dan permainan."</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"Peribadikan"</string>
@@ -469,6 +475,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas dengan perlahan • Penuh dalam masa <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> • Mengecas • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widget pada skrin kunci"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Leret ke kiri untuk memulakan tutorial umum"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Sesuaikan"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Ketepikan"</string>
@@ -554,10 +562,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Mulakan sekarang"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Tiada pemberitahuan"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Tiada pemberitahuan baharu"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Tempoh bertenang pemberitahuan dihidupkan"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Kelantangan, makluman peranti dikurangkan secara automatik hingga 2 minit apabila menerima banyak pemberitahuan serentak."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Matikan"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Buka kunci untuk melihat pemberitahuan lama"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Peranti ini diurus oleh ibu bapa anda"</string>
@@ -1223,7 +1229,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Pengesahan diperlukan. Sentuh penderia cap jari untuk pengesahan."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Panggilan telefon yang sedang berjalan"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Data mudah alih"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Disambungkan"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Disambungkan buat sementara waktu"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Sambungan lemah"</string>
@@ -1377,7 +1382,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Selesai"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Syabas!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Kembali"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Untuk kembali, leret ke kiri atau kanan menggunakan tiga jari di mana-mana sahaja pada pad sentuh."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Pad sentuh menunjukkan tiga jari bergerak ke kanan dan kiri"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Skrin peranti menunjukkan animasi untuk gerak isyarat kembali"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Cahaya latar papan kekunci"</string>
diff --git a/packages/SystemUI/res/values-ms/tiles_states_strings.xml b/packages/SystemUI/res/values-ms/tiles_states_strings.xml
index db63e2c..174e416e 100644
--- a/packages/SystemUI/res/values-ms/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ms/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Mati"</item>
<item msgid="4875147066469902392">"Hidup"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Tidak tersedia"</item>
- <item msgid="2004750556637773692">"Mati"</item>
- <item msgid="8968530753931637871">"Hidup"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Tidak tersedia"</item>
<item msgid="5044688398303285224">"Mati"</item>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index c21b112..d7b20ef 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -127,24 +127,24 @@
<string name="screenrecord_save_error" msgid="5862648532560118815">"ဖန်သားပြင်ရိုက်ကူးမှုကို သိမ်းရာတွင် အမှားရှိသည်"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"ဖန်သားပြင် ရိုက်ကူးမှု စတင်ရာတွင် အမှားအယွင်းရှိနေသည်"</string>
<string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"ရိုက်ကူးခြင်း ရပ်မလား။"</string>
- <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"လောလောဆယ် ဖန်သားပြင်တစ်ခုလုံးကို ရိုက်ကူးနေသည်"</string>
- <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"လောလောဆယ် <xliff:g id="APP_NAME">%1$s</xliff:g> ကို ရိုက်ကူးနေသည်"</string>
+ <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"သင်သည် လက်ရှိတွင် ဖန်သားပြင်တစ်ခုလုံးကို ရိုက်ကူးနေသည်"</string>
+ <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"သင်သည် လက်ရှိတွင် <xliff:g id="APP_NAME">%1$s</xliff:g> ကို ရိုက်ကူးနေသည်"</string>
<string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"ရိုက်ကူးမှု ရပ်ရန်"</string>
<string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"ဖန်သားပြင်ကို မျှဝေနေသည်"</string>
<string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"ဖန်သားပြင်မျှဝေခြင်း ရပ်မလား။"</string>
- <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"<xliff:g id="HOST_APP_NAME">%1$s</xliff:g> ဖြင့် သင့်ဖန်သားပြင်တစ်ခုလုံးကို လောလောဆယ် မျှဝေနေသည်"</string>
- <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"အက်ပ်ဖြင့် သင့်ဖန်သားပြင်တစ်ခုလုံးကို လောလောဆယ် မျှဝေနေသည်"</string>
- <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> ကို လောလောဆယ် မျှဝေနေသည်"</string>
- <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"အက်ပ်ကို လောလောဆယ် မျှဝေနေသည်"</string>
+ <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"သင်သည် လက်ရှိတွင် <xliff:g id="HOST_APP_NAME">%1$s</xliff:g> ဖြင့် ဖန်သားပြင်တစ်ခုလုံးကို မျှဝေနေသည်"</string>
+ <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"သင်သည် လက်ရှိတွင် အက်ပ်တစ်ခုဖြင့် ဖန်သားပြင်တစ်ခုလုံးကို မျှဝေနေသည်"</string>
+ <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"သင်သည် လက်ရှိတွင် <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> ကို မျှဝေနေသည်"</string>
+ <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"သင်သည် လက်ရှိတွင် အက်ပ်ကို မျှဝေနေသည်"</string>
<string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"မျှဝေခြင်း ရပ်ရန်"</string>
<string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"ဖန်သားပြင်ကို ကာစ်လုပ်နေသည်"</string>
<string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"ကာစ်လုပ်ခြင်းကို ရပ်လိုသလား။"</string>
- <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"သင့်ဖန်သားပြင်တစ်ခုလုံးကို <xliff:g id="DEVICE_NAME">%1$s</xliff:g> သို့ လောလောဆယ် ကာစ်လုပ်နေသည်"</string>
- <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"သင့်ဖန်သားပြင်တစ်ခုလုံးကို အနီးတစ်ဝိုက်ရှိ စက်သို့ လောလောဆယ် ကာစ်လုပ်နေသည်"</string>
- <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> ကို <xliff:g id="DEVICE_NAME">%2$s</xliff:g> သို့ လောလောဆယ် ကာစ်လုပ်နေသည်"</string>
- <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> ကို အနီးတစ်ဝိုက်ရှိ စက်သို့ လောလောဆယ် ကာစ်လုပ်နေသည်"</string>
- <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> သို့ လောလောဆယ် ကာစ်လုပ်နေသည်"</string>
- <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"အနီးတစ်ဝိုက်ရှိ စက်သို့ လောလောဆယ် ကာစ်လုပ်နေသည်"</string>
+ <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"သင်သည် လက်ရှိတွင် ဖန်သားပြင်တစ်ခုလုံးကို <xliff:g id="DEVICE_NAME">%1$s</xliff:g> သို့ ကာစ်လုပ်နေသည်"</string>
+ <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"သင်သည် လက်ရှိတွင် ဖန်သားပြင်တစ်ခုလုံးကို အနီးတစ်ဝိုက်ရှိ စက်သို့ ကာစ်လုပ်နေသည်"</string>
+ <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"သင်သည် လက်ရှိတွင် <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> ကို <xliff:g id="DEVICE_NAME">%2$s</xliff:g> သို့ ကာစ်လုပ်နေသည်"</string>
+ <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"သင်သည် လက်ရှိတွင် <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> ကို အနီးတစ်ဝိုက်ရှိ စက်သို့ ကာစ်လုပ်နေသည်"</string>
+ <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"သင်သည် လက်ရှိတွင် <xliff:g id="DEVICE_NAME">%1$s</xliff:g> သို့ ကာစ်လုပ်နေသည်"</string>
+ <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"သင်သည် လက်ရှိတွင် အနီးတစ်ဝိုက်ရှိ စက်သို့ ကာစ်လုပ်နေသည်"</string>
<string name="cast_to_other_device_stop_dialog_button" msgid="6420183747435521834">"ကာစ် ရပ်ရန်"</string>
<string name="close_dialog_button" msgid="4749497706540104133">"ပိတ်ရန်"</string>
<string name="issuerecord_title" msgid="286627115110121849">"ပြဿနာရိုက်ကူးစနစ်"</string>
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"စွမ်းဆောင်ရည်"</string>
<string name="user_interface" msgid="3712869377953950887">"သုံးသူအတွက် ကြားခံစနစ်"</string>
<string name="thermal" msgid="6758074791325414831">"အပူဓာတ်"</string>
+ <string name="custom" msgid="3337456985275158299">"စိတ်ကြိုက်"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"စိတ်ကြိုက်လုပ်ဆောင်ချက်မှတ်တမ်း ဆက်တင်များ"</string>
+ <string name="restore_default" msgid="5259420807486239755">"မူရင်းအတိုင်း ပြန်ပြောင်းရန်"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"လက်တစ်ဖက်သုံးမုဒ်"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"နားကြားကိရိယာ"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"သုံးနေသည်"</string>
@@ -429,10 +432,11 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"ဦးစားပေးမုဒ်"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"ပြီးပြီ"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ဆက်တင်များ"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
- <skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
- <skip />
+ <string name="zen_mode_on" msgid="9085304934016242591">"ဖွင့်"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"ပိတ်"</string>
+ <string name="zen_mode_set_up" msgid="7457957033034460064">"စနစ်ထည့်သွင်းရန်"</string>
+ <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"ဆက်တင်များတွင် စီမံရန်"</string>
+ <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{အသုံးပြုနေသော မုဒ်မရှိပါ}=1{{mode} ကို အသုံးပြုနေသည်}other{မုဒ် # ခုကို အသုံးပြုနေသည်}}"</string>
<string name="zen_priority_introduction" msgid="3159291973383796646">"နှိုးစက်သံ၊ သတိပေးချက်အသံများ၊ ပွဲစဉ်သတိပေးသံများနှင့် သင်ခွင့်ပြုထားသူများထံမှ ဖုန်းခေါ်မှုများမှလွဲ၍ အခြားအသံများနှင့် တုန်ခါမှုများက သင့်ကို အနှောင့်အယှက်ပြုမည် မဟုတ်ပါ။ သို့သော်လည်း သီချင်း၊ ဗီဒီယိုနှင့် ဂိမ်းများအပါအဝင် သင်ကရွေးချယ်ဖွင့်ထားသည့် အရာတိုင်း၏ အသံကိုမူ ကြားနေရဆဲဖြစ်ပါလိမ့်မည်။"</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"နှိုးစက်သံမှလွဲ၍ အခြားအသံများနှင့် တုန်ခါမှုများက သင့်ကို အနှောင့်အယှက်ပြုမည် မဟုတ်ပါ။ သို့သော်လည်း သီချင်း၊ ဗီဒီယိုနှင့် ဂိမ်းများအပါအဝင် သင်ကရွေးချယ်ဖွင့်ထားသည့် အရာတိုင်း၏ အသံကိုမူ ကြားနေရဆဲဖြစ်ပါလိမ့်မည်။"</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"စိတ်ကြိုက် ပြုလုပ်ရန်"</string>
@@ -471,6 +475,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • နှေးကွေးစွာ အားသွင်းနေသည် • အားပြည့်ရန် <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> • အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"လော့ခ်မျက်နှာပြင်ရှိ ဝိဂျက်များ"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"အများသုံးရှင်းလင်းပို့ချချက် စတင်ရန် ဘယ်သို့ပွတ်ဆွဲပါ"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"စိတ်ကြိုက်လုပ်ရန်"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ပယ်ရန်"</string>
@@ -499,8 +505,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"ရွေးချယ်ထားသော ဝိဂျက်ကို တင်ရန်"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"လော့ခ်မျက်နှာပြင် ဝိဂျက်များ"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"တက်ဘလက်လော့ခ်ချထားသော်လည်း မည်သူမဆို လော့ခ်မျက်နှာပြင်ဝိဂျက်ကို ကြည့်နိုင်သည်။"</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ဝိဂျက် ပြန်ဖြုတ်ရန်"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"လော့ခ်မျက်နှာပြင် ဝိဂျက်များ"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ဝိဂျက်သုံး၍ အက်ပ်ဖွင့်ရန်အတွက် သင်ဖြစ်ကြောင်း အတည်ပြုရန်လိုသည်။ ထို့ပြင် သင့်တက်ဘလက် လော့ခ်ချထားချိန်၌ပင် မည်သူမဆို ၎င်းတို့ကို ကြည့်နိုင်ကြောင်း သတိပြုပါ။ ဝိဂျက်အချို့ကို လော့ခ်မျက်နှာပြင်အတွက် ရည်ရွယ်ထားခြင်း မရှိသဖြင့် ဤနေရာတွင် ထည့်ပါက မလုံခြုံနိုင်ပါ။"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"နားလည်ပြီ"</string>
@@ -557,10 +562,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"ယခု စတင်ပါ"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"အကြောင်းကြားချက် မရှိပါ"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"အကြောင်းကြားချက်သစ် မရှိပါ"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"အကြောင်းကြားချက် သတိပေးမှု လျှော့ချခြင်း ဖွင့်ထားသည်"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"အကြောင်းကြားချက်များစွာ တစ်ပြိုင်နက်ရပါက သင့်စက်၏ အသံအတိုးအကျယ်နှင့် သတိပေးချက်ကို ၂ မိနစ်ကြာသည်အထိ အလိုအလျောက်လျှော့ချသည်။"</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"ပိတ်ရန်"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"အကြောင်းကြားချက်ဟောင်းကြည့်ရန် လော့ခ်ဖွင့်ပါ"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ဤစက်ပစ္စည်းကို သင့်မိဘက စီမံခန့်ခွဲသည်"</string>
@@ -1226,7 +1229,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"အထောက်အထားစိစစ်ခြင်း လိုအပ်သည်။ အထောက်အထားစိစစ်ရန် လက်ဗွေ အာရုံခံကိရိယာကို ထိပါ။"</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"လက်ရှိ ဖုန်းခေါ်ဆိုမှု"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"မိုဘိုင်းဒေတာ"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"ချိတ်ဆက်ထားသည်"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ယာယီချိတ်ဆက်ထားသည်"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"ချိတ်ဆက်မှုအားနည်းသည်"</string>
@@ -1380,7 +1382,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ပြီးပြီ"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"တော်ပါပေသည်။"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ပြန်သွားရန်"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"ပြန်သွားရန်အတွက် တာ့ချ်ပက်တွင် မည်သည့်နေရာ၌မဆို လက်သုံးချောင်းသုံး၍ ဘယ် (သို့) ညာသို့ ပွတ်ဆွဲပါ။"</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"တာ့ချ်ပက်တွင် ဘယ်ညာရွှေ့နေသော လက်သုံးချောင်းကို ပြထားသည်"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"စက်စခရင်တွင် နောက်သို့လက်ဟန်အတွက် လှုပ်ရှားသက်ဝင်ပုံကို ပြထားသည်"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ကီးဘုတ်နောက်မီး"</string>
@@ -1388,28 +1393,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"အိမ်ထိန်းချုပ်မှုများ"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"အိမ်ထိန်းချုပ်မှုများကို စခရင်နားချိန်ပုံအဖြစ် အမြန်ဝင်ကြည့်ရန်"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"နောက်ပြန်ရန်"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"နောက်ပြန်သွားရန် တာ့ချ်ပက်ပေါ်တွင် လက်သုံးချောင်းဖြင့် ဘယ် (သို့) ညာသို့ ပွတ်ဆွဲပါ"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"ပင်မစာမျက်နှာသို့ သွားရန် တာ့ချ်ပက်ပေါ်တွင် လက်သုံးချောင်းဖြင့် အပေါ်သို့ပွတ်ဆွဲပါ"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"လတ်တလောအက်ပ်များကို ကြည့်ရန် တာ့ချ်ပက်ပေါ်တွင် လက်သုံးချောင်းဖြင့် အပေါ်သို့ပွတ်ဆွဲပြီး ဖိထားပါ"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"သင့်အက်ပ်အားလုံးကြည့်ရန် ကီးဘုတ်ပေါ်ရှိ လုပ်ဆောင်ချက်ကီးကို နှိပ်ပါ"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"နောက်ပြန်သွားရန် သင့်တာ့ချ်ပက်ကို သုံးပါ"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"လက်သုံးချောင်းဖြင့် ဘယ် (သို့) ညာသို့ ပွတ်ဆွဲပါ။ လက်ဟန်များ ပိုမိုလေ့လာရန် တို့ပါ။"</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"ပင်မစာမျက်နှာသို့ သွားရန် သင့်တာ့ချ်ပက်ကို သုံးပါ"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"လက်သုံးချောင်းဖြင့် အပေါ်သို့ပွတ်ဆွဲပါ။ လက်ဟန်များ ပိုမိုလေ့လာရန် တို့ပါ။"</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"လတ်တလောအက်ပ်များကို ကြည့်ရန် သင့်တာ့ချ်ပက်ကို သုံးပါ"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"လက်သုံးချောင်းဖြင့် အပေါ်သို့ပွတ်ဆွဲပြီး ဖိထားပါ။ လက်ဟန်များ ပိုမိုလေ့လာရန် တို့ပါ။"</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"အက်ပ်အားလုံးကြည့်ရန် သင့်ကီးဘုတ်ကို သုံးပါ"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"လုပ်ဆောင်ချက်ကီးကို အချိန်မရွေးနှိပ်ပါ။ လက်ဟန်များ ပိုမိုလေ့လာရန် တို့ပါ။"</string>
</resources>
diff --git a/packages/SystemUI/res/values-my/tiles_states_strings.xml b/packages/SystemUI/res/values-my/tiles_states_strings.xml
index 4e3334f..f665a00a 100644
--- a/packages/SystemUI/res/values-my/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-my/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"ပိတ်"</item>
<item msgid="4875147066469902392">"ဖွင့်"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"မရနိုင်ပါ"</item>
- <item msgid="2004750556637773692">"ပိတ်"</item>
- <item msgid="8968530753931637871">"ဖွင့်"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"မရနိုင်ပါ"</item>
<item msgid="5044688398303285224">"ပိတ်"</item>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 149e130..07b979f 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -127,24 +127,24 @@
<string name="screenrecord_save_error" msgid="5862648532560118815">"Feil ved lagring av skjermopptaket"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Feil ved start av skjermopptaket"</string>
<string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"Vil du stoppe opptaket?"</string>
- <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"Du tar opp hele skjermen"</string>
- <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Du tar opp <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"Du tar nå opp hele skjermen"</string>
+ <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Du tar nå opp <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Stopp opptaket"</string>
<string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"Deler skjermen"</string>
<string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Vil du slutte å dele skjermen?"</string>
- <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Du deler hele skjermen med <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string>
- <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Du deler hele skjermen med en app"</string>
- <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Du deler <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string>
- <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"Du deler en app"</string>
+ <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Du deler nå hele skjermen med <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string>
+ <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Du deler nå hele skjermen med en app"</string>
+ <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Du deler nå <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string>
+ <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"Du deler nå en app"</string>
<string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"Slutt å dele"</string>
<string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"Caster skjermen"</string>
<string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Vil du stoppe castingen?"</string>
- <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Du caster hele skjermen til <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
- <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Du caster hele skjermen til en enhet i nærheten"</string>
- <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Du caster <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> til <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
- <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"Du caster <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> til en enhet i nærheten"</string>
- <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"Du caster til <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
- <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"Du caster skjermen til en enhet i nærheten"</string>
+ <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Du caster nå hele skjermen til <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Du caster nå hele skjermen til en enhet i nærheten"</string>
+ <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Du caster nå <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> til <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"Du caster nå <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> til en enhet i nærheten"</string>
+ <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"Du caster nå til <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"Du caster nå skjermen til en enhet i nærheten"</string>
<string name="cast_to_other_device_stop_dialog_button" msgid="6420183747435521834">"Stopp castingen"</string>
<string name="close_dialog_button" msgid="4749497706540104133">"Lukk"</string>
<string name="issuerecord_title" msgid="286627115110121849">"Funksjon for opptak av problemer"</string>
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Ytelse"</string>
<string name="user_interface" msgid="3712869377953950887">"Brukergrensesnitt"</string>
<string name="thermal" msgid="6758074791325414831">"Termisk"</string>
+ <string name="custom" msgid="3337456985275158299">"Egendefinert"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Innstillinger for egendefinert spor"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Gjenopprett standard"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Enhåndsmodus"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Høreapparater"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktiv"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritetsmoduser"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Ferdig"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Innstillinger"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"På"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Av"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Du blir ikke forstyrret av lyder og vibrasjoner, med unntak av alarmer, påminnelser, aktiviteter og oppringere du angir. Du kan fremdeles høre alt du velger å spille av, for eksempel musikk, videoer og spill."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Du blir ikke forstyrret av lyder og vibrasjoner, med unntak av alarmer. Du kan fremdeles høre alt du velger å spille av, for eksempel musikk, videoer og spill."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader sakte • Fulladet om <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> • Lader • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Moduler på låseskjermen"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Sveip til venstre for å starte fellesveiledningen"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Tilpass"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Lukk"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"plasser den valgte modulen"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Moduler på låseskjermen"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Hvem som helst kan se moduler på låseskjermen – selv om nettbrettet er låst."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"velg bort modul"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Låseskjermmoduler"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"For å åpne en app ved hjelp av en modul må du bekrefte at det er deg. Husk også at hvem som helst kan se dem, selv om nettbrettet er låst. Noen moduler er kanskje ikke laget for å være på låseskjermen og kan være utrygge å legge til der."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Greit"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Start nå"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Ingen varsler"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Ingen nye varsler"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Varseldemping er slått på"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Enhetsvolumet og varsler reduseres automatisk i opptil 2 min når du får for mange varsler samtidig."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Slå av"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Lås opp for å se eldre varsler"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Denne enheten administreres av forelderen din"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentisering kreves. Trykk på fingeravtrykkssensoren for å autentisere."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Pågående telefonsamtale"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobildata"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Tilkoblet"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Koblet til midlertidig"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Dårlig forbindelse"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Ferdig"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Bra jobbet!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Gå tilbake"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"For å gå tilbake, sveip til venstre eller høyre med tre fingre hvor som helst på styreflaten."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"En styreflate med tre fingre som beveger seg til høyre og venstre"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Enhetsskjerm med animasjonen for tilbakebevegelse"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Bakgrunnslys for tastatur"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Hjemkontroller"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Gå raskt til hjemkontrollene som skjermsparer"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Angre"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"For å gå tilbake, sveip til venstre eller høyre med tre fingre på styreflaten"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"For å gå til startsiden, sveip opp med tre fingre på styreflaten"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"For å se nylige apper, sveip opp og hold med tre fingre på styreflaten"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"For å se alle appene dine, trykk på handlingstasten på tastaturet"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Bruk styreflaten for å gå tilbake"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Sveip til venstre eller høyre med tre fingre. Trykk for å lære flere bevegelser."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Bruk styreflaten for å gå til startsiden"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Sveip opp med tre fingre. Trykk for å lære flere bevegelser."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Bruk styreflaten for å se nylige apper"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Sveip opp og hold med tre fingre. Trykk for å lære flere bevegelser."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Bruk tastaturet for å se alle apper"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Trykk på handlingstasten når som helst. Trykk for å lære flere bevegelser."</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/tiles_states_strings.xml b/packages/SystemUI/res/values-nb/tiles_states_strings.xml
index e3d8eff..a9efd1d 100644
--- a/packages/SystemUI/res/values-nb/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-nb/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Av"</item>
<item msgid="4875147066469902392">"På"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Utilgjengelig"</item>
- <item msgid="2004750556637773692">"Av"</item>
- <item msgid="8968530753931637871">"På"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Utilgjengelig"</item>
<item msgid="5044688398303285224">"Av"</item>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 01f7b40..67843fd 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"पर्फर्मेन्स"</string>
<string name="user_interface" msgid="3712869377953950887">"युजर इन्टरफेस"</string>
<string name="thermal" msgid="6758074791325414831">"थर्मल"</string>
+ <string name="custom" msgid="3337456985275158299">"कस्टम"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"कस्टम ट्रेस सेटिङ"</string>
+ <string name="restore_default" msgid="5259420807486239755">"डिफल्ट सेटिङ रिस्टोर गर्नुहोस्"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"एक हाते मोड"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"हियरिङ डिभाइसहरू"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"सक्रिय छ"</string>
@@ -431,6 +434,12 @@
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"सेटिङ"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"अन छ"</string>
<string name="zen_mode_off" msgid="1736604456618147306">"अफ छ"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
+ <skip />
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
+ <skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"तपाईंलाई अलार्म, रिमाइन्डर, कार्यक्रम र तपाईंले निर्दिष्ट गर्नुभएका कलरहरू बाहेकका ध्वनि र कम्पनहरूले बाधा पुऱ्याउने छैनन्। तपाईंले अझै सङ्गीत, भिडियो र खेलहरू लगायत आफूले प्ले गर्न छनौट गरेका जुनसुकै कुरा सुन्न सक्नुहुनेछ।"</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"तपाईंलाई अलार्महरू बाहेकका ध्वनि र कम्पनहरूले बाधा पुऱ्याउने छैनन्। तपाईंले अझै सङ्गीत, भिडियो र खेलहरू लगायत आफूले प्ले गर्न छनौट गरेका जुनसुकै कुरा सुन्न सक्नुहुनेछ।"</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">" कस्टम बनाउनुहोस्"</string>
@@ -469,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • बिस्तारै चार्ज हुँदै छ • <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> • चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा फुल चार्ज हुने छ"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"लक स्क्रिनमा भएका विजेटहरू"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"कम्युनल ट्युटोरियल सुरु गर्न बायाँतिर स्वाइप गर्नुहोस्"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"कस्टमाइज गर्नुहोस्"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"खारेज गर्नुहोस्"</string>
@@ -554,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"अहिले न"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"कुनै सूचनाहरू छैनन्"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"कुनै पनि नयाँ सूचना छैन"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"नोटिफिकेसन कुलडाउन अन छ"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"तपाईंले एकै पटक धेरै नोटिफिकेसन प्राप्त गर्दा बढीमा २ मिनेटसम्म तपाईंको डिभाइसको भोल्युम र अलर्टहरूको सङ्ख्या स्वतः घटाइन्छ।"</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"अफ गर्नुहोस्"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"पुराना सूचनाहरू हेर्न अनलक गर्नुहोस्"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"यो डिभाइस तपाईंका अभिभावक व्यवस्थापन गर्नुहुन्छ"</string>
@@ -1223,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"पुष्टि गर्नु पर्ने हुन्छ। पुष्टि गर्न फिंगरप्रिन्ट सेन्सर छुनुहोस्।"</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"जारी फोन कल"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"इन्टरनेटमा कनेक्ट गरिएको छ"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"यसमा केही समयका लागि कनेक्ट गरिएको हो"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"इन्टरनेट राम्री चलेको छैन"</string>
@@ -1377,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"सम्पन्न भयो"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"अद्भुत!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"पछाडि जानुहोस्"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"पछाडि जान तिन वटा औँलाले टचप्याडमा कतै छोएर बायाँ वा दायाँतिर स्वाइप गर्नुहोस्।"</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"तिन वटा औँला दायाँ र बायाँ सारेको देखाइएको टचप्याड"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"पछाडि जाने जेस्चरको एनिमेसन देखाइएको डिभाइसको स्क्रिन"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"किबोर्ड ब्याकलाइट"</string>
diff --git a/packages/SystemUI/res/values-ne/tiles_states_strings.xml b/packages/SystemUI/res/values-ne/tiles_states_strings.xml
index e0c517a..c1b2f34 100644
--- a/packages/SystemUI/res/values-ne/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ne/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"अफ छ"</item>
<item msgid="4875147066469902392">"अन छ"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"उपलब्ध छैन"</item>
- <item msgid="2004750556637773692">"अफ छ"</item>
- <item msgid="8968530753931637871">"अन छ"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"उपलब्ध छैन"</item>
<item msgid="5044688398303285224">"अफ छ"</item>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 65fda39..d259a3d 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Prestaties"</string>
<string name="user_interface" msgid="3712869377953950887">"Gebruikersinterface"</string>
<string name="thermal" msgid="6758074791325414831">"Thermisch"</string>
+ <string name="custom" msgid="3337456985275158299">"Aangepast"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Aangepaste traceringsinstellingen"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Standaardinstellingen terugzetten"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Bediening met 1 hand"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hoortoestellen"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Actief"</string>
@@ -431,6 +434,12 @@
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Instellingen"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Aan"</string>
<string name="zen_mode_off" msgid="1736604456618147306">"Uit"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
+ <skip />
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
+ <skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Je wordt niet gestoord door geluiden en trillingen, behalve bij wekkers, herinneringen, afspraken en specifieke bellers die je selecteert. Je kunt nog steeds alles horen wat je wilt afspelen, waaronder muziek, video\'s en games."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Je wordt niet gestoord door geluiden en trillingen, behalve bij wekkers. Je kunt nog steeds alles horen wat je wilt afspelen, waaronder muziek, video\'s en games."</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"Aanpassen"</string>
@@ -469,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Langzaam opladen • Vol over <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> • Opladen • Vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets op het vergrendelscherm"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe naar links om de communitytutorial te starten"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Aanpassen"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Sluiten"</string>
@@ -554,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Nu starten"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Geen meldingen"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Geen nieuwe meldingen"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Afkoelperiode van meldingen staat aan"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Je apparaatvolume en meldingen worden automatisch maximaal 2 minuten beperkt als je te veel meldingen tegelijk krijgt."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Uitzetten"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Ontgrendel om oudere meldingen te zien"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Dit apparaat wordt beheerd door je ouder"</string>
@@ -1223,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Verificatie vereist. Raak de vingerafdruksensor aan om de verificatie uit te voeren."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Actief telefoongesprek"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiele data"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Verbonden"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tijdelijk verbonden"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Matige verbinding"</string>
@@ -1377,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Klaar"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Goed werk!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Terug"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Als je wilt teruggaan, swipe je met 3 vingers naar links of rechts op de touchpad."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad met 3 vingers die naar rechts en links bewegen"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Apparaatscherm met animatie voor teruggebaar"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Achtergrondverlichting van toetsenbord"</string>
diff --git a/packages/SystemUI/res/values-nl/tiles_states_strings.xml b/packages/SystemUI/res/values-nl/tiles_states_strings.xml
index b23dc91..c5d9361 100644
--- a/packages/SystemUI/res/values-nl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-nl/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Uit"</item>
<item msgid="4875147066469902392">"Aan"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Niet beschikbaar"</item>
- <item msgid="2004750556637773692">"Uit"</item>
- <item msgid="8968530753931637871">"Aan"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Niet beschikbaar"</item>
<item msgid="5044688398303285224">"Uit"</item>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 5bc77eb..11681c9 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"ପରଫରମାନ୍ସ"</string>
<string name="user_interface" msgid="3712869377953950887">"ୟୁଜର ଇଣ୍ଟରଫେସ"</string>
<string name="thermal" msgid="6758074791325414831">"ଥର୍ମାଲ"</string>
+ <string name="custom" msgid="3337456985275158299">"କଷ୍ଟମ"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"କଷ୍ଟମ ଟ୍ରେସ ସେଟିଂସ"</string>
+ <string name="restore_default" msgid="5259420807486239755">"ଡିଫଲ୍ଟ ରିଷ୍ଟୋର କରନ୍ତୁ"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ଏକ-ହାତ ମୋଡ"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ଶ୍ରବଣ ଡିଭାଇସଗୁଡ଼ିକ"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"ସକ୍ରିୟ"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"ପ୍ରାଥମିକତା ମୋଡ"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"ହୋଇଗଲା"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ସେଟିଂସ"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"ଚାଲୁ ଅଛି"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"ବନ୍ଦ ଅଛି"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"ଆଲାର୍ମ, ରିମାଇଣ୍ଡର୍, ଇଭେଣ୍ଟ ଏବଂ ଆପଣ ନିର୍ଦ୍ଦିଷ୍ଟ କରିଥିବା କଲର୍ଙ୍କ ବ୍ୟତୀତ ଆପଣଙ୍କ ଧ୍ୟାନ ଅନ୍ୟ କୌଣସି ଧ୍ୱନୀ ଏବଂ ଭାଇବ୍ରେଶନ୍ରେ ଆକର୍ଷଣ କରାଯିବନାହିଁ। ମ୍ୟୁଜିକ୍, ଭିଡିଓ ଏବଂ ଗେମ୍ ସମେତ ନିଜେ ଚଲାଇବାକୁ ବାଛିଥିବା ଅନ୍ୟ ସବୁକିଛି ଆପଣ ଶୁଣିପାରିବେ।"</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"ଆଲାର୍ମ ବ୍ୟତୀତ ଆପଣଙ୍କ ଧ୍ୟାନ ଅନ୍ୟ କୌଣସି ଧ୍ୱନୀ ଏବଂ ଭାଇବ୍ରେଶନ୍ରେ ଆକର୍ଷଣ କରାଯିବନାହିଁ। ମ୍ୟୁଜିକ୍, ଭିଡିଓ ଏବଂ ଗେମ୍ ସମେତ ନିଜେ ଚଲାଇବାକୁ ବାଛିଥିବା ଅନ୍ୟ ସବୁକିଛି ଆପଣ ଶୁଣିପାରିବେ।"</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଧୀରେ ଚାର୍ଜ ହେଉଛି • <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> • ଚାର୍ଜ ହେଉଛି • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ରେ ସମ୍ପୂର୍ଣ୍ଣ ହେବ"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ଲକ ସ୍କ୍ରିନରେ ଥିବା ୱିଜେଟଗୁଡ଼ିକ"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"କମ୍ୟୁନାଲ ଟ୍ୟୁଟୋରିଆଲ ଆରମ୍ଭ କରିବା ପାଇଁ ବାମକୁ ସ୍ୱାଇପ କରନ୍ତୁ"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"କଷ୍ଟମାଇଜ କରନ୍ତୁ"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ଖାରଜ କରନ୍ତୁ"</string>
@@ -497,10 +506,9 @@
<string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"ୱିଜେଟ ଚୟନ କରନ୍ତୁ"</string>
<string name="accessibility_action_label_remove_widget" msgid="3373779447448758070">"ୱିଜେଟକୁ କାଢ଼ି ଦିଅନ୍ତୁ"</string>
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"ଚୟନିତ ୱିଜେଟ ରଖନ୍ତୁ"</string>
- <string name="communal_widget_picker_title" msgid="1953369090475731663">"ଲକ ସ୍କ୍ରିନ ୱିଜେଟଗୁଡ଼ିକ"</string>
+ <string name="communal_widget_picker_title" msgid="1953369090475731663">"ଲକ ସ୍କ୍ରିନ ୱିଜେଟ"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"ଆପଣଙ୍କ ଟାବଲେଟ ଲକ ଥିଲେ ମଧ୍ୟ ଯେ କୌଣସି ବ୍ୟକ୍ତି ଲକ ସ୍କ୍ରିନରେ ୱିଜେଟକୁ ଭ୍ୟୁ କରିପାରିବେ।"</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ୱିଜେଟକୁ ଅଚୟନ କରନ୍ତୁ"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ଲକ ସ୍କ୍ରିନ ୱିଜେଟ"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ଏକ ୱିଜେଟ ବ୍ୟବହାର କରି ଗୋଟିଏ ଆପ ଖୋଲିବା ପାଇଁ ଏହା ଆପଣ ଅଟନ୍ତି ବୋଲି ଆପଣଙ୍କୁ ଯାଞ୍ଚ କରିବାକୁ ହେବ। ଆହୁରି ମଧ୍ୟ, ଆପଣଙ୍କ ଟାବଲେଟ ଲକ ଥିଲେ ମଧ୍ୟ ଯେ କୌଣସି ବ୍ୟକ୍ତି ଏହାକୁ ଭ୍ୟୁ କରିପାରିବେ ବୋଲି ମନେ ରଖନ୍ତୁ। କିଛି ୱିଜେଟ ଆପଣଙ୍କ ଲକ ସ୍କ୍ରିନ ପାଇଁ ଉଦ୍ଦିଷ୍ଟ ହୋଇନଥାଇପାରେ ଏବଂ ଏଠାରେ ଯୋଗ କରିବା ଅସୁରକ୍ଷିତ ହୋଇପାରେ।"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"ବୁଝିଗଲି"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"ବର୍ତ୍ତମାନ ଆରମ୍ଭ କରନ୍ତୁ"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"କୌଣସି ବିଜ୍ଞପ୍ତି ନାହିଁ"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"କୌଣସି ନୂଆ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ନାହିଁ"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"ବିଜ୍ଞପ୍ତି କୁଲଡାଉନ ଚାଲୁ ଅଛି"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"ଆପଣ ଥରକେ ଏକାଧିକ ବିଜ୍ଞପ୍ତି ପ୍ରାପ୍ତ କଲେ ଆପଣଙ୍କ ଡିଭାଇସର ଭଲ୍ୟୁମ ଓ ଆଲର୍ଟ ସ୍ୱତଃ 2 ମିନିଟ ପର୍ଯ୍ୟନ୍ତ କମ ହୁଏ।"</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ପୁରୁଣା ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ଦେଖିବାକୁ ଅନଲକ କରନ୍ତୁ"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ଏହି ଡିଭାଇସ୍ ଆପଣଙ୍କ ବାପାମାଙ୍କ ଦ୍ୱାରା ପରିଚାଳିତ"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ପ୍ରମାଣୀକରଣ ଆବଶ୍ୟକ। ପ୍ରମାଣୀକରଣ କରିବାକୁ ଟିପଚିହ୍ନ ସେନ୍ସରକୁ ସ୍ପର୍ଶ କରନ୍ତୁ।"</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ଚାଲୁଥିବା ଫୋନ୍ କଲ୍"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"ମୋବାଇଲ ଡାଟା"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"ସଂଯୋଗ କରାଯାଇଛି"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ଅସ୍ଥାୟୀ ରୂପେ କନେକ୍ଟ କରାଯାଇଛି"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"ଦୁର୍ବଳ କନେକ୍ସନ"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ହୋଇଗଲା"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ବଢ଼ିଆ କାମ!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ପଛକୁ ଫେରନ୍ତୁ"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"ପଛକୁ ଫେରିବା ପାଇଁ ଯେ କୌଣସି ସ୍ଥାନରେ ତିନି ଆଙ୍ଗୁଠି ବ୍ୟବହାର କରି ବାମ କିମ୍ବା ଡାହାଣକୁ ସ୍ୱାଇପ କରନ୍ତୁ।"</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ଡାହାଣ ଏବଂ ବାମକୁ ତିନି ଆଙ୍ଗୁଠି ମୁଭ କରୁଥିବା ଟଚପେଡ ଦେଖାଉଛି"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"ଡିଭାଇସ ସ୍କ୍ରିନ ବେକ ଜେଶ୍ଚର ପାଇଁ ଆନିମେସନ ଦେଖାଉଛି"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"କୀବୋର୍ଡ ବେକଲାଇଟ"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"ହୋମ କଣ୍ଟ୍ରୋଲ୍ସ"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"ସ୍କ୍ରିନସେଭର ଭାବେ ହୋମ କଣ୍ଟ୍ରୋଲ୍ସକୁ ଶୀଘ୍ର ଆକ୍ସେସ କରନ୍ତୁ"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"ଅନଡୁ କରନ୍ତୁ"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"ପଛକୁ ଫେରିବା ପାଇଁ ଟଚପେଡରେ ତିନୋଟି ଆଙ୍ଗୁଠିରେ ବାମ କିମ୍ବା ଡାହାଣ ସ୍ୱାଇପ କରନ୍ତୁ"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"ହୋମକୁ ଯିବା ପାଇଁ ଟଚପେଡରେ ତିନୋଟି ଆଙ୍ଗୁଠିରେ ଉପରକୁ ସ୍ୱାଇପ କରନ୍ତୁ"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"ବର୍ତ୍ତମାନର ଆପ୍ସ ଭ୍ୟୁ କରିବାକୁ, ଟଚପେଡରେ ତିନୋଟି ଆଙ୍ଗୁଠିରେ ଉପରକୁ ସ୍ୱାଇପ କରି ଧରି ରଖନ୍ତୁ"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ଆପଣଙ୍କ ସମସ୍ତ ଆପ୍ସ ଭ୍ୟୁ କରିବା ପାଇଁ ଆପଣଙ୍କ କୀବୋର୍ଡରେ ଆକ୍ସନ କୀ\'କୁ ଦବାନ୍ତୁ"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"ପଛକୁ ଫେରିବା ପାଇଁ ଆପଣଙ୍କ ଟଚପେଡକୁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"ତିନୋଟି ଆଙ୍ଗୁଠିରେ ବାମ ବା ଡାହାଣକୁ ସ୍ୱାଇପ କରନ୍ତୁ। ଜେଶ୍ଚରଗୁଡ଼ିକ ବିଷୟରେ ଅଧିକ ଜାଣିବାକୁ ଟାପ କରନ୍ତୁ।"</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"ହୋମକୁ ଯିବା ପାଇଁ ଆପଣଙ୍କ ଟଚପେଡ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"ତିନୋଟି ଆଙ୍ଗୁଠି ବ୍ୟବହାର କରି ଉପରକୁ ସ୍ୱାଇପ କରନ୍ତୁ। ଜେଶ୍ଚରଗୁଡ଼ିକ ବିଷୟରେ ଅଧିକ ଜାଣିବାକୁ ଟାପ କରନ୍ତୁ।"</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"ବର୍ତ୍ତମାନର ଆପ୍ସ ଭ୍ୟୁ କରିବାକୁ ଆପଣଙ୍କ ଟଚପେଡକୁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"ତିନୋଟି ଆଙ୍ଗୁଠିରେ ଉପରକୁ ସ୍ୱାଇପ କରି ଧରି ରଖନ୍ତୁ। ଜେଶ୍ଚରଗୁଡ଼ିକ ବିଷୟରେ ଅଧିକ ଜାଣିବାକୁ ଟାପ କରନ୍ତୁ।"</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"ସମସ୍ତ ଆପ୍ସ ଭ୍ୟୁ କରିବା ପାଇଁ ଆପଣଙ୍କ କୀବୋର୍ଡକୁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ଯେ କୌଣସି ସମୟରେ ଆକ୍ସନ କୀ\'କୁ ଦବାନ୍ତୁ। ଜେଶ୍ଚରଗୁଡ଼ିକ ବିଷୟରେ ଅଧିକ ଜାଣିବାକୁ ଟାପ କରନ୍ତୁ।"</string>
</resources>
diff --git a/packages/SystemUI/res/values-or/tiles_states_strings.xml b/packages/SystemUI/res/values-or/tiles_states_strings.xml
index 3ab7e5d..fe187c2 100644
--- a/packages/SystemUI/res/values-or/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-or/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"ବନ୍ଦ ଅଛି"</item>
<item msgid="4875147066469902392">"ଚାଲୁ ଅଛି"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"ଅନୁପଲବ୍ଧ"</item>
- <item msgid="2004750556637773692">"ବନ୍ଦ ଅଛି"</item>
- <item msgid="8968530753931637871">"ଚାଲୁ ଅଛି"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"ଉପଲବ୍ଧ ନାହିଁ"</item>
<item msgid="5044688398303285224">"ବନ୍ଦ ଅଛି"</item>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 9692789..ef642ff 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"ਕਾਰਗੁਜ਼ਾਰੀ"</string>
<string name="user_interface" msgid="3712869377953950887">"ਯੂਜ਼ਰ ਇੰਟਰਫ਼ੇਸ"</string>
<string name="thermal" msgid="6758074791325414831">"ਥਰਮਲ"</string>
+ <string name="custom" msgid="3337456985275158299">"ਵਿਉਂਤਬੱਧ"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"ਵਿਉਂਤਬੱਧ ਟ੍ਰੇਸ ਸੈਟਿੰਗਾਂ"</string>
+ <string name="restore_default" msgid="5259420807486239755">"ਪੂਰਵ ਨਿਰਧਾਰਿਤ ਨੂੰ ਮੁੜ-ਬਹਾਲ ਕਰੋ"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ਇੱਕ ਹੱਥ ਮੋਡ"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ਸੁਣਨ ਵਾਲੇ ਡੀਵਾਈਸ"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"ਕਿਰਿਆਸ਼ੀਲ"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"ਤਰਜੀਹ ਮੋਡ"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"ਹੋ ਗਿਆ"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ਸੈਟਿੰਗਾਂ"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"ਚਾਲੂ"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"ਬੰਦ"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"ਧੁਨੀਆਂ ਅਤੇ ਥਰਥਰਾਹਟਾਂ ਤੁਹਾਨੂੰ ਪਰੇਸ਼ਾਨ ਨਹੀਂ ਕਰਨਗੀਆਂ, ਸਿਵਾਏ ਅਲਾਰਮਾਂ, ਯਾਦ-ਦਹਾਨੀਆਂ, ਵਰਤਾਰਿਆਂ, ਅਤੇ ਤੁਹਾਡੇ ਵੱਲੋਂ ਨਿਰਧਾਰਤ ਕੀਤੇ ਕਾਲਰਾਂ ਦੀ ਸੂਰਤ ਵਿੱਚ। ਤੁਸੀਂ ਅਜੇ ਵੀ ਸੰਗੀਤ, ਵੀਡੀਓ ਅਤੇ ਗੇਮਾਂ ਸਮੇਤ ਆਪਣੀ ਚੋਣ ਅਨੁਸਾਰ ਕੁਝ ਵੀ ਸੁਣ ਸਕਦੇ ਹੋ।"</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"ਧੁਨੀਆਂ ਅਤੇ ਥਰਥਰਾਹਟਾਂ ਤੁਹਾਨੂੰ ਪਰੇਸ਼ਾਨ ਨਹੀਂ ਕਰਨਗੀਆਂ, ਸਿਵਾਏ ਅਲਾਰਮਾਂ ਦੀ ਸੂਰਤ ਵਿੱਚ। ਤੁਸੀਂ ਅਜੇ ਵੀ ਸੰਗੀਤ, ਵੀਡੀਓ ਅਤੇ ਗੇਮਾਂ ਸਮੇਤ ਆਪਣੀ ਚੋਣ ਅਨੁਸਾਰ ਕੁਝ ਵੀ ਸੁਣ ਸਕਦੇ ਹੋ।"</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <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> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਵਿਜੇਟ"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ਭਾਈਚਾਰਕ ਟਿਊਟੋਰੀਅਲ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਖੱਬੇ ਪਾਸੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ਵਿਉਂਤਬੱਧ ਕਰੋ"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ਖਾਰਜ ਕਰੋ"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"ਚੁਣੇ ਗਏ ਵਿਜੇਟ ਲਈ ਥਾਂ ਚੁਣੋ"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"ਲਾਕ ਸਕ੍ਰੀਨ ਵਿਜੇਟ"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"ਕੋਈ ਵੀ ਤੁਹਾਡੀ ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਵਿਜੇਟ ਦੇਖ ਸਕਦਾ ਹੈ, ਭਾਵੇਂ ਤੁਹਾਡਾ ਟੈਬਲੈੱਟ ਲਾਕ ਹੋਵੇ।"</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ਵਿਜੇਟ ਨੂੰ ਅਣਚੁਣਿਆ ਕਰੋ"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ਲਾਕ ਸਕ੍ਰੀਨ ਵਿਜੇਟ"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ਵਿਜੇਟ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਐਪ ਖੋਲ੍ਹਣ ਲਈ, ਤੁਹਾਨੂੰ ਇਹ ਪੁਸ਼ਟੀ ਕਰਨ ਦੀ ਲੋੜ ਪਵੇਗੀ ਕਿ ਇਹ ਤੁਸੀਂ ਹੀ ਹੋ। ਨਾਲ ਹੀ, ਇਹ ਵੀ ਧਿਆਨ ਵਿੱਚ ਰੱਖੋ ਕਿ ਕੋਈ ਵੀ ਉਨ੍ਹਾਂ ਨੂੰ ਦੇਖ ਸਕਦਾ ਹੈ, ਭਾਵੇਂ ਤੁਹਾਡੀ ਟੈਬਲੈੱਟ ਲਾਕ ਹੋਵੇ। ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਕੁਝ ਵਿਜੇਟ ਤੁਹਾਡੀ ਲਾਕ ਸਕ੍ਰੀਨ ਲਈ ਨਾ ਬਣੇ ਹੋਣ ਅਤੇ ਉਨ੍ਹਾਂ ਨੂੰ ਇੱਥੇ ਸ਼ਾਮਲ ਕਰਨਾ ਅਸੁਰੱਖਿਅਤ ਹੋਵੇ।"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"ਸਮਝ ਲਿਆ"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"ਹੁਣੇ ਸ਼ੁਰੂ ਕਰੋ"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"ਕੋਈ ਸੂਚਨਾ ਨਹੀਂ"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"ਕੋਈ ਨਵੀਂ ਸੂਚਨਾ ਨਹੀਂ ਹੈ"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"ਨੋਟੀਫ਼ਿਕੇਸ਼ਨ ਕੂਲਡਾਊਨ ਚਾਲੂ ਹੈ"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"ਇੱਕ ਵਾਰ \'ਚ ਕਈ ਸੂਚਨਾਵਾਂ ਮਿਲਣ \'ਤੇ, ਡੀਵਾਈਸ ਦੀ ਅਵਾਜ਼ ਤੇ ਅਲਰਟ ਵੱਧੋ-ਵੱਧ 2 ਮਿੰਟਾਂ ਲਈ ਆਪਣੇ ਆਪ ਘਟ ਹੋ ਜਾਂਦੇ ਹਨ।"</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"ਬੰਦ ਕਰੋ"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ਪੁਰਾਣੀਆਂ ਸੂਚਨਾਵਾਂ ਦੇਖਣ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ਇਸ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਬੰਧਨ ਤੁਹਾਡੇ ਮਾਂ-ਪਿਓ ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ਪ੍ਰਮਾਣੀਕਰਨ ਲੋੜੀਂਦਾ ਹੈ। ਪ੍ਰਮਾਣਿਤ ਕਰਨ ਲਈ ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਨੂੰ ਸਪਰਸ਼ ਕਰੋ।"</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ਜਾਰੀ ਫ਼ੋਨ ਕਾਲ"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"ਮੋਬਾਈਲ ਡਾਟਾ"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"ਕਨੈਕਟ ਹੈ"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ਕੁਝ ਸਮੇਂ ਲਈ ਕਨੈਕਟ ਹੈ"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"ਖਰਾਬ ਕਨੈਕਸ਼ਨ"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ਹੋ ਗਿਆ"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ਬਹੁਤ ਵਧੀਆ!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ਵਾਪਸ ਜਾਓ"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"ਵਾਪਸ ਜਾਣ ਲਈ, ਟੱਚਪੈਡ \'ਤੇ ਕਿਤੇ ਵੀ ਤਿੰਨ ਉਂਗਲਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਖੱਬੇ ਜਾਂ ਸੱਜੇ ਪਾਸੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ।"</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ਟੱਚਪੈਡ \'ਤੇ ਤਿੰਨ ਉਂਗਲਾਂ ਨੂੰ ਸੱਜੇ ਅਤੇ ਖੱਬੇ ਪਾਸੇ ਵੱਲ ਲਿਜਾਂਦੇ ਹੋਏ ਦਿਖਾਇਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"ਡੀਵਾਈਸ ਦੀ ਸਕ੍ਰੀਨ \'ਤੇ ਪਿੱਛੇ ਜਾਣ ਵਾਲੇ ਇਸ਼ਾਰੇ ਲਈ ਐਨੀਮੇਸ਼ਨ ਦਿਖਾਇਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ਕੀ-ਬੋਰਡ ਬੈਕਲਾਈਟ"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"ਹੋਮ ਕੰਟਰੋਲ"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"ਸਕ੍ਰੀਨ-ਸੇਵਰ ਵਜੋਂ ਆਪਣੇ ਹੋਮ ਕੰਟਰੋਲਾਂ ਤੱਕ ਤੁਰੰਤ ਪਹੁੰਚ ਕਰੋ"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"ਅਣਕੀਤਾ ਕਰੋ"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"ਪਿੱਛੇ ਜਾਣ ਲਈ, ਟੱਚਪੈਡ \'ਤੇ ਤਿੰਨ ਉਂਗਲਾਂ ਨਾਲ ਖੱਬੇ ਜਾਂ ਸੱਜੇ ਪਾਸੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"ਹੋਮ \'ਤੇ ਜਾਣ ਲਈ, ਟੱਚਪੈਡ \'ਤੇ ਤਿੰਨ ਉਂਗਲਾਂ ਨਾਲ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"ਹਾਲੀਆ ਐਪਾਂ ਨੂੰ ਦੇਖਣ ਲਈ, ਟੱਚਪੈਡ \'ਤੇ ਤਿੰਨ ਉਂਗਲਾਂ ਨਾਲ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰ ਕੇ ਦਬਾਈ ਰੱਖੋ"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ਆਪਣੀਆਂ ਸਾਰੀਆਂ ਐਪਾਂ ਨੂੰ ਦੇਖਣ ਲਈ, ਆਪਣੇ ਕੀ-ਬੋਰਡ \'ਤੇ ਕਾਰਵਾਈ ਕੁੰਜੀ ਨੂੰ ਦਬਾਓ"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"ਪਿੱਛੇ ਜਾਣ ਲਈ ਆਪਣੇ ਟੱਚਪੈਡ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"ਤਿੰਨ ਉਂਗਲਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਖੱਬੇ ਜਾਂ ਸੱਜੇ ਪਾਸੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ। ਹੋਰ ਇਸ਼ਾਰਿਆਂ ਨੂੰ ਜਾਣਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"ਹੋਮ \'ਤੇ ਜਾਣ ਲਈ ਆਪਣੇ ਟੱਚਪੈਡ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"ਤਿੰਨ ਉਂਗਲਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ। ਹੋਰ ਇਸ਼ਾਰਿਆਂ ਨੂੰ ਜਾਣਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"ਹਾਲੀਆ ਐਪਾਂ ਦੇਖਣ ਲਈ ਆਪਣੇ ਟੱਚਪੈਡ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"ਤਿੰਨ ਉਂਗਲਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰ ਕੇ ਦਬਾਈ ਰੱਖੋ। ਹੋਰ ਇਸ਼ਾਰਿਆਂ ਨੂੰ ਜਾਣਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"ਸਾਰੀਆਂ ਐਪਾਂ ਨੂੰ ਦੇਖਣ ਲਈ ਆਪਣਾ ਕੀ-ਬੋਰਡ ਵਰਤੋ"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ਕਿਸੇ ਵੀ ਸਮੇਂ ਕਾਰਵਾਈ ਕੁੰਜੀ ਦਬਾਓ। ਹੋਰ ਇਸ਼ਾਰਿਆਂ ਨੂੰ ਜਾਣਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pa/tiles_states_strings.xml b/packages/SystemUI/res/values-pa/tiles_states_strings.xml
index c91062d..62dc05a 100644
--- a/packages/SystemUI/res/values-pa/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pa/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"ਬੰਦ ਹੈ"</item>
<item msgid="4875147066469902392">"ਚਾਲੂ ਹੈ"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"ਉਪਲਬਧ ਨਹੀਂ"</item>
- <item msgid="2004750556637773692">"ਬੰਦ"</item>
- <item msgid="8968530753931637871">"ਚਾਲੂ"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"ਅਣਉਪਲਬਧ ਹੈ"</item>
<item msgid="5044688398303285224">"ਬੰਦ ਹੈ"</item>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 3a01cc9..d0e1e11 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Wydajność"</string>
<string name="user_interface" msgid="3712869377953950887">"Interfejs"</string>
<string name="thermal" msgid="6758074791325414831">"Termografia"</string>
+ <string name="custom" msgid="3337456985275158299">"Niestandardowe"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Niestandardowe ustawienia śladu"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Przywróć wartości domyślne"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Tryb jednej ręki"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Urządzenia słuchowe"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktywne"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Tryby priorytetowe"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gotowe"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ustawienia"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Wł."</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Wył."</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Nie będą Cię niepokoić żadne dźwięki ani wibracje z wyjątkiem alarmów, przypomnień, wydarzeń i połączeń od wybranych osób. Będziesz słyszeć wszystkie odtwarzane treści, takie jak muzyka, filmy czy gry."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Nie będą Cię niepokoić żadne dźwięki ani wibracje z wyjątkiem alarmów. Będziesz słyszeć wszystkie odtwarzane treści, takie jak muzyka, filmy czy gry."</string>
@@ -471,6 +478,8 @@
<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_action_open_communal_hub" msgid="3081702792413787849">"Widżety na ekranie blokady"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Aby uruchomić wspólny samouczek, przeciągnij palcem w lewo"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Dostosuj"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Zamknij"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"umieść wybrany widżet"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Widżety na ekranie blokady"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Każdy zobaczy widżety na ekranie blokady, nawet gdy tablet jest zablokowany."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"odznacz widżet"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widżety na ekranie blokady"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Aby otworzyć aplikację za pomocą widżetu, musisz potwierdzić swoją tożsamość. Pamiętaj też, że każdy będzie mógł wyświetlić widżety nawet wtedy, gdy tablet będzie zablokowany. Niektóre widżety mogą nie być przeznaczone do umieszczenia na ekranie blokady i ich dodanie w tym miejscu może być niebezpieczne."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Rozpocznij teraz"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Brak powiadomień"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Brak nowych powiadomień"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Wyciszanie powiadomień jest włączone"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Gdy otrzymasz za dużo powiadomień, dźwięk i alerty zostaną automatycznie wyciszone na maks. 2 min."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Wyłącz"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Odblokuj i zobacz starsze powiadomienia"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Tym urządzeniem zarządza Twój rodzic"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Wymagane uwierzytelnienie. Dotknij czytnika liniii papilarnych, by uwierzytelnić."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Aktywne połączenie"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilna transmisja danych"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Połączono"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tymczasowe połączenie"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Słabe połączenie"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gotowe"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Świetnie!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Wróć"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Aby wrócić, przesuń 3 palcami w lewo lub w prawo w dowolnym miejscu touchpada."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"3 palce na touchpadzie poruszające się w prawo i w lewo"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ekran urządzenia z animacją gestu cofania"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Podświetlenie klawiatury"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Sterowanie domem"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Szybki dostęp do sterowania domem na wygaszaczu ekranu"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Cofnij"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Aby przejść wstecz, przesuń w prawo lub lewo za pomocą 3 palców na touchpadzie."</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Aby przejść do ekranu głównego, przesuń w górę za pomocą 3 palców na touchpadzie"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Aby wyświetlić ostatnie aplikacje, przesuń w górę za pomocą 3 palców na touchpadzie i przytrzymaj."</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Aby wyświetlić wszystkie swoje aplikacje, naciśnij klawisz działania na klawiaturze"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Przechodzenie wstecz za pomocą touchpada"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Przesuń w prawo lub lewo za pomocą 3 palców. Kliknij, aby poznać więcej gestów."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Przechodzenie do ekranu głównego za pomocą touchpada"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Przesuń w górę za pomocą 3 palców. Kliknij, aby poznać więcej gestów."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Wyświetlanie ostatnio używanych aplikacji za pomocą touchpada"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Przesuń w górę za pomocą 3 palców i przytrzymaj. Kliknij, aby poznać więcej gestów."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Wyświetlanie wszystkich aplikacji za pomocą klawiatury"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Naciśnij klawisz działania w dowolnym momencie. Kliknij, aby poznać więcej gestów."</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/tiles_states_strings.xml b/packages/SystemUI/res/values-pl/tiles_states_strings.xml
index 2190cf8..5aa719f 100644
--- a/packages/SystemUI/res/values-pl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pl/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Wyłączone"</item>
<item msgid="4875147066469902392">"Włączone"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Niedostępne"</item>
- <item msgid="2004750556637773692">"Wyłączono"</item>
- <item msgid="8968530753931637871">"Włączono"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Niedostępny"</item>
<item msgid="5044688398303285224">"Wyłączona"</item>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 6a2bc58..e74f578 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -218,7 +218,7 @@
<string name="biometric_re_enroll_notification_content" msgid="8685925877186288180">"Ação necessária para melhorar a segurança e o desempenho"</string>
<string name="fingerprint_re_enroll_notification_title" msgid="4539432429683916604">"Configurar o Desbloqueio por impressão digital de novo"</string>
<string name="fingerprint_re_enroll_notification_name" msgid="630798657797645704">"Desbloqueio por impressão digital"</string>
- <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Configurar o Desbloqueio por impressão digital"</string>
+ <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Configurar o Desbloqueio por impressão digital"</string>
<string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"Os modelos e as imagens atuais serão excluídos para reconfigurar o Desbloqueio por impressão digital.\n\nDepois disso, você vai precisar configurar esse recurso de novo para desbloquear o smartphone com o dedo ou confirmar sua identidade."</string>
<string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"O modelo e as imagens atuais serão excluídos para reconfigurar o Desbloqueio por impressão digital.\n\nDepois disso, você vai precisar configurar esse recurso de novo para desbloquear o smartphone com o dedo ou confirmar sua identidade."</string>
<string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"Não foi possível configurar o Desbloqueio por impressão digital. Acesse as Configurações e tente de novo."</string>
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Desempenho"</string>
<string name="user_interface" msgid="3712869377953950887">"Interface do usuário"</string>
<string name="thermal" msgid="6758074791325414831">"Térmico"</string>
+ <string name="custom" msgid="3337456985275158299">"Personalizado"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Configurações de rastreamento personalizado"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Restaurar padrão"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo uma mão"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Aparelhos auditivos"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Ativos"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modos prioritários"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Concluído"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configurações"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Ativado"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Desativado"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Você não será perturbado por sons e vibrações, exceto alarmes, lembretes, eventos e chamadas de pessoas especificadas. No entanto, você ouvirá tudo o que decidir reproduzir, como músicas, vídeos e jogos."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Você não será perturbado por sons e vibrações, exceto alarmes. No entanto, você ouvirá tudo o que decidir reproduzir, como músicas, vídeos e jogos."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta • Conclusão em <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> • Carregando • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets na tela de bloqueio"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Deslize para a esquerda para iniciar o tutorial compartilhado"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dispensar"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"posicionar widget selecionado"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgets da tela de bloqueio"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Todos podem ver os widgets na tela de bloqueio, mesmo com o tablet bloqueado."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"desmarcar widget"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets da tela de bloqueio"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Para abrir um app usando um widget, você precisará confirmar sua identidade. Além disso, não se esqueça que qualquer pessoa pode ver os widgets, mesmo quando o tablet está bloqueado. Alguns widgets podem não ter sido criados para ficar na tela de bloqueio e fazer isso talvez não seja seguro."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Entendi"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Iniciar agora"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Sem notificações"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Nenhuma notificação nova"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"O recurso de atenuar notificações está ativo"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Volume e alertas do disp. são reduzidos por até 2 min quando você recebe muitas notificações juntas."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Desativar"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueie p/ acessar notificações antigas"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo é gerenciado pelo seu familiar responsável"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticação obrigatória. Toque no sensor de impressão digital para autenticar."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada em andamento"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Dados móveis"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporariamente conectado"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexão fraca"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Concluído"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Muito bem!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Voltar"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Para voltar, deslize para a esquerda ou direita usando 3 dedos em qualquer lugar do touchpad."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad mostrando 3 dedos deslizando para a direita e esquerda"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Tela do dispositivo mostrando a animação do gesto de volta"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Luz de fundo do teclado"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Automação residencial"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Controles de automação residencial no protetor de tela"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Desfazer"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Se quiser voltar, deslize para a esquerda ou direita com três dedos no touchpad"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Se quiser acessar a tela inicial, deslize para cima com três dedos no touchpad"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Se quiser ver os apps recentes, deslize para cima e pressione com três dedos no touchpad"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Para ver todos os apps, pressione a tecla de ação no teclado"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Use o touchpad para voltar"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Deslize para a esquerda ou direita usando três dedos. Toque para aprender outros gestos."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Use o touchpad para acessar a tela inicial"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Deslize para cima usando três dedos. Toque para aprender outros gestos."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Use o touchpad para ver os apps recentes"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Deslize para cima e pressione com três dedos. Toque para aprender outros gestos."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use o teclado para ver todos os apps"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pressione a tecla de ação a qualquer momento. Toque para aprender outros gestos."</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml b/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml
index 097543b..3526c77 100644
--- a/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Desativado"</item>
<item msgid="4875147066469902392">"Ativado"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Indisponível"</item>
- <item msgid="2004750556637773692">"Desativado"</item>
- <item msgid="8968530753931637871">"Ativado"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Indisponível"</item>
<item msgid="5044688398303285224">"Desativada"</item>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index d514a8f..a21f475 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Desempenho"</string>
<string name="user_interface" msgid="3712869377953950887">"Interface do utilizador"</string>
<string name="thermal" msgid="6758074791325414831">"Térmico"</string>
+ <string name="custom" msgid="3337456985275158299">"Personalizado"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Definições de rastreio personalizadas"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Restaurar predefinição"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo para uma mão"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Disp. auditivos"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Ativos"</string>
@@ -431,6 +434,12 @@
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Definições"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Ativado"</string>
<string name="zen_mode_off" msgid="1736604456618147306">"Desativado"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
+ <skip />
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
+ <skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Não é incomodado por sons e vibrações, exceto de alarmes, lembretes, eventos e autores de chamadas que especificar. Continua a ouvir tudo o que optar por reproduzir, incluindo música, vídeos e jogos."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Não é incomodado por sons e vibrações, exceto de alarmes. Continua a ouvir tudo o que optar por reproduzir, incluindo música, vídeos e jogos."</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"Personalizar"</string>
@@ -469,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar lentamente • Carga completa em <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> • A carregar • Carga completa em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets no ecrã de bloqueio"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Deslize rapidamente para a esquerda para iniciar o tutorial coletivo"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Ignorar"</string>
@@ -554,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Começar agora"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Sem notificações"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Não existem novas notificações"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"O repouso das notificações está ativado"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"O volume e os alertas são reduzidos automaticamente durante até 2 minutos quando recebe muitas notificações de uma vez."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Desativar"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueie e veja notificações antigas"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo é gerido pelos teus pais"</string>
@@ -1223,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticação necessária. Toque no sensor de impressões digitais para autenticar."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada telefónica em curso"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Dados móveis"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Ligado"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Ligado temporariamente"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Ligação fraca"</string>
@@ -1377,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Concluir"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Muito bem!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Voltar"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Para retroceder, deslize rapidamente para a esquerda ou direita com três dedos em qualquer parte do touchpad."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad a mostrar três dedos a moverem-se para a direita e esquerda"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ecrã de dispositivo a mostrar uma animação do gesto para retroceder"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Luz do teclado"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml b/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml
index d7a245a..34a5ed7 100644
--- a/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Desligado"</item>
<item msgid="4875147066469902392">"Ligado"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Indisponível"</item>
- <item msgid="2004750556637773692">"Desativado"</item>
- <item msgid="8968530753931637871">"Ativado"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Indisponível"</item>
<item msgid="5044688398303285224">"Desligada"</item>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 6a2bc58..e74f578 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -218,7 +218,7 @@
<string name="biometric_re_enroll_notification_content" msgid="8685925877186288180">"Ação necessária para melhorar a segurança e o desempenho"</string>
<string name="fingerprint_re_enroll_notification_title" msgid="4539432429683916604">"Configurar o Desbloqueio por impressão digital de novo"</string>
<string name="fingerprint_re_enroll_notification_name" msgid="630798657797645704">"Desbloqueio por impressão digital"</string>
- <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Configurar o Desbloqueio por impressão digital"</string>
+ <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Configurar o Desbloqueio por impressão digital"</string>
<string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"Os modelos e as imagens atuais serão excluídos para reconfigurar o Desbloqueio por impressão digital.\n\nDepois disso, você vai precisar configurar esse recurso de novo para desbloquear o smartphone com o dedo ou confirmar sua identidade."</string>
<string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"O modelo e as imagens atuais serão excluídos para reconfigurar o Desbloqueio por impressão digital.\n\nDepois disso, você vai precisar configurar esse recurso de novo para desbloquear o smartphone com o dedo ou confirmar sua identidade."</string>
<string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"Não foi possível configurar o Desbloqueio por impressão digital. Acesse as Configurações e tente de novo."</string>
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Desempenho"</string>
<string name="user_interface" msgid="3712869377953950887">"Interface do usuário"</string>
<string name="thermal" msgid="6758074791325414831">"Térmico"</string>
+ <string name="custom" msgid="3337456985275158299">"Personalizado"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Configurações de rastreamento personalizado"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Restaurar padrão"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo uma mão"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Aparelhos auditivos"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Ativos"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modos prioritários"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Concluído"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configurações"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Ativado"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Desativado"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Você não será perturbado por sons e vibrações, exceto alarmes, lembretes, eventos e chamadas de pessoas especificadas. No entanto, você ouvirá tudo o que decidir reproduzir, como músicas, vídeos e jogos."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Você não será perturbado por sons e vibrações, exceto alarmes. No entanto, você ouvirá tudo o que decidir reproduzir, como músicas, vídeos e jogos."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta • Conclusão em <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> • Carregando • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets na tela de bloqueio"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Deslize para a esquerda para iniciar o tutorial compartilhado"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dispensar"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"posicionar widget selecionado"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgets da tela de bloqueio"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Todos podem ver os widgets na tela de bloqueio, mesmo com o tablet bloqueado."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"desmarcar widget"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets da tela de bloqueio"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Para abrir um app usando um widget, você precisará confirmar sua identidade. Além disso, não se esqueça que qualquer pessoa pode ver os widgets, mesmo quando o tablet está bloqueado. Alguns widgets podem não ter sido criados para ficar na tela de bloqueio e fazer isso talvez não seja seguro."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Entendi"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Iniciar agora"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Sem notificações"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Nenhuma notificação nova"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"O recurso de atenuar notificações está ativo"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Volume e alertas do disp. são reduzidos por até 2 min quando você recebe muitas notificações juntas."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Desativar"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueie p/ acessar notificações antigas"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo é gerenciado pelo seu familiar responsável"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticação obrigatória. Toque no sensor de impressão digital para autenticar."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada em andamento"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Dados móveis"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporariamente conectado"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexão fraca"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Concluído"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Muito bem!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Voltar"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Para voltar, deslize para a esquerda ou direita usando 3 dedos em qualquer lugar do touchpad."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad mostrando 3 dedos deslizando para a direita e esquerda"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Tela do dispositivo mostrando a animação do gesto de volta"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Luz de fundo do teclado"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Automação residencial"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Controles de automação residencial no protetor de tela"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Desfazer"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Se quiser voltar, deslize para a esquerda ou direita com três dedos no touchpad"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Se quiser acessar a tela inicial, deslize para cima com três dedos no touchpad"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Se quiser ver os apps recentes, deslize para cima e pressione com três dedos no touchpad"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Para ver todos os apps, pressione a tecla de ação no teclado"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Use o touchpad para voltar"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Deslize para a esquerda ou direita usando três dedos. Toque para aprender outros gestos."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Use o touchpad para acessar a tela inicial"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Deslize para cima usando três dedos. Toque para aprender outros gestos."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Use o touchpad para ver os apps recentes"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Deslize para cima e pressione com três dedos. Toque para aprender outros gestos."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use o teclado para ver todos os apps"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pressione a tecla de ação a qualquer momento. Toque para aprender outros gestos."</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/tiles_states_strings.xml b/packages/SystemUI/res/values-pt/tiles_states_strings.xml
index 097543b..3526c77 100644
--- a/packages/SystemUI/res/values-pt/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pt/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Desativado"</item>
<item msgid="4875147066469902392">"Ativado"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Indisponível"</item>
- <item msgid="2004750556637773692">"Desativado"</item>
- <item msgid="8968530753931637871">"Ativado"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Indisponível"</item>
<item msgid="5044688398303285224">"Desativada"</item>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index b129e51..d0895ad 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Performanță"</string>
<string name="user_interface" msgid="3712869377953950887">"Interfața de utilizare"</string>
<string name="thermal" msgid="6758074791325414831">"Termal"</string>
+ <string name="custom" msgid="3337456985275158299">"Personalizat"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Setări de urmărire personalizate"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Revino la valoarea prestabilită"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modul cu o mână"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Aparate auditive"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Activ"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Moduri cu prioritate"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gata"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Setări"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Activat"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Dezactivat"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Se vor anunța prin sunete și vibrații numai alarmele, mementourile, evenimentele și apelanții specificați de tine. Totuși, vei auzi tot ce alegi să redai, inclusiv muzică, videoclipuri și jocuri."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Se vor anunța prin sunete și vibrații numai alarmele. Totuși, vei auzi tot ce alegi să redai, inclusiv muzică, videoclipuri și jocuri."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă lent • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string>
<string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgeturi pe ecranul de blocare"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Glisează spre stânga pentru a începe tutorialul pentru comunitate"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizează"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Respinge"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"plasează widgetul selectat"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgeturi pe ecranul de blocare"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Oricine vede widgeturile pe ecranul de blocare, chiar dacă tableta e blocată"</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"deselectează widgetul"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgeturi pe ecranul de blocare"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Pentru a deschide o aplicație folosind un widget, va trebui să-ți confirmi identitatea. În plus, reține că oricine poate să vadă widgeturile, chiar dacă tableta este blocată. Este posibil ca unele widgeturi să nu fi fost create pentru ecranul de blocare și poate fi nesigur să le adaugi aici."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Începe acum"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Nicio notificare"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Nicio notificare nouă"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Reducerea sunetului notificărilor este activată"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Volumul și alertele dispozitivului sunt reduse automat timp de până la 2 min. când primești prea multe notificări odată"</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Dezactivează"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Deblochează ca să vezi notificări vechi"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Dispozitivul este gestionat de unul dintre părinți"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentificare obligatorie. Atinge senzorul de amprentă pentru a te autentifica."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Apel telefonic în desfășurare"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Date mobile"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Conectat"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectat temporar"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexiune slabă"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gata"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Excelent!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Înapoi"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Pentru a reveni, glisează spre stânga sau spre dreapta cu trei degete oriunde pe touchpad."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad cu trei degete care se mișcă spre dreapta și spre stânga"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ecran de dispozitiv cu o animație pentru gestul Înapoi"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Iluminarea din spate a tastaturii"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Comenzi pentru locuință"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Accesează comenzile pentru locuință ca screensaver"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Anulează"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Pentru a reveni, glisează spre stânga sau spre dreapta cu trei degete pe touchpad"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Ca să accesezi pagina de pornire, glisează în sus cu trei degete pe touchpad"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Ca să vezi aplicațiile recente, glisează în sus și ține apăsat cu trei degete pe touchpad"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Ca să vezi toate aplicațiile, apasă tasta de acțiuni de pe tastatură"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Folosește-ți touchpadul ca să revii"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Glisează la stânga sau la dreapta cu trei degete. Atinge ca să înveți mai multe gesturi."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Folosește-ți touchpadul ca să accesezi pagina de pornire"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Glisează în sus cu trei degete. Atinge ca să înveți mai multe gesturi."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Folosește-ți touchpadul ca să vezi aplicațiile recente"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Glisează în sus și ține apăsat cu trei degete. Atinge ca să înveți mai multe gesturi."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Folosește-ți tastatura ca să vezi toate aplicațiile"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Apasă oricând tasta de acțiuni. Atinge ca să înveți mai multe gesturi."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/tiles_states_strings.xml b/packages/SystemUI/res/values-ro/tiles_states_strings.xml
index 22b5070..a68f140 100644
--- a/packages/SystemUI/res/values-ro/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ro/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Dezactivată"</item>
<item msgid="4875147066469902392">"Activată"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Indisponibil"</item>
- <item msgid="2004750556637773692">"Dezactivat"</item>
- <item msgid="8968530753931637871">"Activat"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Indisponibilă"</item>
<item msgid="5044688398303285224">"Dezactivată"</item>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index ebbac59..3811185 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -119,7 +119,7 @@
<string name="screenrecord_continue" msgid="4055347133700593164">"Начать"</string>
<string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Идет запись видео с экрана"</string>
<string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Идет запись видео с экрана и звука"</string>
- <string name="screenrecord_taps_label" msgid="1595690528298857649">"Показывать прикосновения к экрану"</string>
+ <string name="screenrecord_taps_label" msgid="1595690528298857649">"Показывать прикосновения"</string>
<string name="screenrecord_stop_label" msgid="72699670052087989">"Остановить"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Поделиться"</string>
<string name="screenrecord_save_title" msgid="1886652605520893850">"Видео с экрана сохранено"</string>
@@ -378,7 +378,7 @@
<string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Запись видео с экрана"</string>
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Начать"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Остановить"</string>
- <string name="qs_record_issue_label" msgid="8166290137285529059">"Запись неисправности"</string>
+ <string name="qs_record_issue_label" msgid="8166290137285529059">"Запись неполадки"</string>
<string name="qs_record_issue_start" msgid="2979831312582567056">"Начать"</string>
<string name="qs_record_issue_stop" msgid="3531747965741982657">"Остановить"</string>
<string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Отчет об ошибке"</string>
@@ -387,7 +387,10 @@
<string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Запись экрана"</string>
<string name="performance" msgid="6552785217174378320">"Производительность"</string>
<string name="user_interface" msgid="3712869377953950887">"Интерфейс"</string>
- <string name="thermal" msgid="6758074791325414831">"Тепловизор"</string>
+ <string name="thermal" msgid="6758074791325414831">"Нагрев"</string>
+ <string name="custom" msgid="3337456985275158299">"Свой вариант"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Свои настройки трассировки"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Восстановить настройки по умолчанию"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Режим управления одной рукой"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слуховые аппараты"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Активно"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Режимы приоритета"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Готово"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Настройки"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Включено"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Отключено"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Вас не будут отвлекать звуки и вибрация, за исключением сигналов будильника, напоминаний, уведомлений о мероприятиях и звонков от помеченных контактов. Вы по-прежнему будете слышать включенную вами музыку, видео, игры и т. д."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Вас не будут отвлекать звуки и вибрация, за исключением сигналов будильника. Вы по-прежнему будете слышать включенную вами музыку, видео, игры и т. д."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Медленная зарядка • Осталось <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> • Зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Виджеты на заблокированном экране"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Чтобы ознакомиться с руководством, проведите по экрану влево"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Настроить"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Закрыть"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"разместить выбранный виджет"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Виджеты на заблокированном экране"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Они видны всем, даже если планшет заблокирован."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"отменить выбор виджета"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Виджеты на заблокированном экране"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Чтобы открыть приложение, используя виджет, вам нужно будет подтвердить свою личность. Обратите внимание, что виджеты видны всем, даже если планшет заблокирован. Некоторые виджеты не предназначены для использования на заблокированном экране. Добавлять их туда может быть небезопасно."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"ОК"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Начать"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Нет уведомлений."</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Новых уведомлений нет"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Снижение громкости уведомлений включено"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Если придет слишком много уведомлений, на две минуты громкость и количество оповещений уменьшатся."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Отключить"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Разблокируйте, чтобы увидеть уведомления"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Устройством управляет один из родителей."</string>
@@ -659,7 +665,7 @@
<string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Нажмите, чтобы выключить звук. Специальные возможности могут прекратить работу."</string>
<string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Нажмите, чтобы включить вибрацию."</string>
<string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Нажмите, чтобы выключить звук."</string>
- <string name="volume_panel_noise_control_title" msgid="7413949943872304474">"Контроль уровня шума"</string>
+ <string name="volume_panel_noise_control_title" msgid="7413949943872304474">"Контроль шума"</string>
<string name="volume_panel_spatial_audio_title" msgid="3367048857932040660">"Пространственное звучание"</string>
<string name="volume_panel_spatial_audio_off" msgid="4177490084606772989">"Отключено"</string>
<string name="volume_panel_spatial_audio_fixed" msgid="3136080137827746046">"Без отслеживания"</string>
@@ -677,8 +683,8 @@
<string name="volume_panel_hint_unmute" msgid="4831850937582282340">"Включить звук аудиопотока \"%s\""</string>
<string name="volume_panel_hint_muted" msgid="1124844870181285320">"без звука"</string>
<string name="volume_panel_hint_vibrate" msgid="4136223145435914132">"вибросигнал"</string>
- <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> – запущено здесь:"</string>
- <string name="media_output_title_without_playing" msgid="3825663683169305013">"Проигрывание аудио:"</string>
+ <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> – играет здесь:"</string>
+ <string name="media_output_title_without_playing" msgid="3825663683169305013">"Аудио будет звучать здесь"</string>
<string name="media_output_title_ongoing_call" msgid="208426888064112006">"Настройки вызова"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Строка состояния"</string>
@@ -735,7 +741,7 @@
<string name="notification_channel_summary_automatic_silenced" msgid="7403004439649872047">"<b>Статус:</b> понижено до уровня \"Без звука\""</string>
<string name="notification_channel_summary_automatic_promoted" msgid="1301710305149590426">"<b>Статус:</b> уровень важности повышен"</string>
<string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"<b>Статус:</b> уровень важности понижен"</string>
- <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"Появляется в верхней части уведомлений о сообщениях, а также в качестве фото профиля на заблокированном экране"</string>
+ <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"Вверху списка уведомлений о разговорах и в виде фото профиля на заблокированном экране"</string>
<string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Появляется в верхней части уведомлений о сообщениях, в виде всплывающего чата, а также в качестве фото профиля на заблокированном экране."</string>
<string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Появляется в верхней части уведомлений о сообщениях, а также в виде фото профиля на заблокированном экране, прерывает режим \"Не беспокоить\"."</string>
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Появляется в верхней части уведомлений о сообщениях, в виде всплывающего чата, а также в качестве фото профиля на заблокированном экране, прерывает режим \"Не беспокоить\"."</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Требуется аутентификация. Приложите палец к сканеру отпечатков."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Текущий вызов"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобильный интернет"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Подключено"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Временное подключение"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Слабый сигнал"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Отлично!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Чтобы вернуться, проведите тремя пальцами влево или вправо по сенсорной панели."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Три пальца двигаются вправо и влево по сенсорной панели"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"На экране устройства показана анимация для жеста \"Назад\""</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Подсветка клавиатуры"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Управление домом"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Быстрый доступ к управлению домом через заставку"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Отменить"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Чтобы вернуться назад, проведите по сенсорной панели тремя пальцами влево или вправо."</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Чтобы перейти на главный экран, проведите по сенсорной панели тремя пальцами вверх."</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Чтобы увидеть недавние приложения, проведите по сенсорной панели тремя пальцами вверх и удерживайте."</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Чтобы открыть список всех своих приложений, нажмите клавишу действия."</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Используйте сенсорную панель, чтобы возвращаться назад"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Для этого проведите тремя пальцами влево или вправо. Нажмите, чтобы посмотреть другие жесты."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Используйте сенсорную панель, чтобы переходить на главный экран"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Для этого проведите тремя пальцами вверх. Нажмите, чтобы посмотреть другие жесты."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Используйте сенсорную панель, чтобы смотреть список недавних приложений"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Для этого проведите тремя пальцами вверх и удерживайте. Нажмите, чтобы посмотреть другие жесты."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Открывайте список всех приложений с помощью клавиатуры"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Для этого можно использовать клавишу действия. Нажмите, чтобы посмотреть другие жесты."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/tiles_states_strings.xml b/packages/SystemUI/res/values-ru/tiles_states_strings.xml
index 4d4f39e..592937c 100644
--- a/packages/SystemUI/res/values-ru/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ru/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Откл."</item>
<item msgid="4875147066469902392">"Вкл."</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Недоступно"</item>
- <item msgid="2004750556637773692">"Отключено"</item>
- <item msgid="8968530753931637871">"Включено"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Функция недоступна"</item>
<item msgid="5044688398303285224">"Откл."</item>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index eb447b9..46b82e3 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"කාර්ය සාධනය"</string>
<string name="user_interface" msgid="3712869377953950887">"පරිශීලක අතුරු මුහුණත"</string>
<string name="thermal" msgid="6758074791325414831">"තාප"</string>
+ <string name="custom" msgid="3337456985275158299">"අභිරුචි"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"අභිරුචි ලුහුබැඳීම් සැකසීම්"</string>
+ <string name="restore_default" msgid="5259420807486239755">"පෙරනිමිය ප්රතිසාධනය කරන්න"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"තනි අත් ප්රකාරය"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ශ්රවණ උපාංග"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"ක්රියාකාරී"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"ප්රමුඛතා ප්රකාර"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"නිමයි"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"සැකසීම්"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"ක්රියාත්මකයි"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"ක්රියාවිරහිතයි"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"එලාම සිහිකැඳවීම්, සිදුවීම්, සහ ඔබ සඳහන් කළ අමතන්නන් හැර, ශබ්ද සහ කම්පනවලින් ඔබට බාධා නොවනු ඇත. සංගීතය, වීඩියෝ, සහ ක්රීඩා ඇතුළු ඔබ වාදනය කිරීමට තෝරන ලද සියලු දේ ඔබට තවම ඇසෙනු ඇත."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"එලාම හැර, ශබ්ද සහ කම්පනවලින් ඔබට බාධා නොවනු ඇත. සංගීතය, වීඩියෝ, සහ ක්රීඩා ඇතුළු ඔබ වාදනය කිරීමට තෝරන ලද සියලු දේ ඔබට තවම ඇසෙනු ඇත."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • සෙමින් ආරෝපණය වෙමින් • <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> • ආරෝපණය වෙමින් • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>කින් සම්පූර්ණ වේ"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"අගුළු තිරයෙහි විජට්"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"පොදු නිබන්ධනය ආරම්භ කිරීමට වමට ස්වයිප් කරන්න"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"අභිරුචිකරණය කරන්න"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"අස් කරන්න"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"තෝරන ලද විජට්ටුව තබන්න"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"අගුළු තිර විජට්"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"ඔබේ ටැබ්ලටය අගුළු දමා තිබුණත්, ඕනෑම කෙනෙකුට ඔබේ අගුළු තිරයෙහි විජට් බැලිය හැක."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"විජට් නොතෝරන්න"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"අගුළු තිර විජට්"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"විජට් එකක් භාවිතයෙන් යෙදුමක් විවෘත කිරීමට, ඔබට ඒ ඔබ බව සත්යාපනය කිරීමට අවශ්ය වනු ඇත. එසේම, ඔබේ ටැබ්ලටය අගුළු දමා ඇති විට පවා ඕනෑම කෙනෙකුට ඒවා බැලිය හැකි බව මතක තබා ගන්න. සමහර විජට් ඔබේ අගුළු තිරය සඳහා අදහස් කර නොතිබිය හැකි අතර මෙහි එක් කිරීමට අනාරක්ෂිත විය හැක."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"තේරුණා"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"දැන් අරඹන්න"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"දැනුම්දීම් නැත"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"නව දැනුම්දීම් නැත"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"දැනුම්දීම් සිසිල් කිරීම ක්රියාත්මකයි"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"ඔබට එකවර දැනුම්දීම් වැඩි ප්රමාණයක් ලැබෙන විට ඔබේ උපාංග පරිමාව සහ ඇඟවීම් මිනිත්තු 2ක් දක්වා ස්වයංක්රීයව අඩු වේ."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"ක්රියාවිරහිත කරන්න"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"පැරණි දැනුම්දීම් බැලීමට අගුළු හරින්න"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"මෙම උපාංගය ඔබගේ මාපියන්ගෙන් අයකු විසින් කළමනාකරණය කෙරේ"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"සත්යාපනය අවශ්යයි. සත්යාපනය කිරීමට ඇඟිලි සලකුණු සංවේදකය ස්පර්ශ කරන්න."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ක්රියාත්මක වන දුරකථන ඇමතුම"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"ජංගම දත්ත"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"සම්බන්ධයි"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"තාවකාලිකව සම්බන්ධ කළා"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"දුර්වල සම්බන්ධතාව"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"නිමයි"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"අනර්ඝ වැඩක්!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ආපස්සට යන්න"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"ආපසු යාමට, ස්පර්ශ පුවරුවේ ඕනෑම තැනක ඇඟිලි තුනක් භාවිතයෙන් වමට හෝ දකුණට ස්වයිප් කරන්න."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ඇඟිලි තුනක් දකුණට සහ වමට චලනය වන බව පෙන්වන ස්පර්ශක පුවරුව"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"පසුපස අභිනය සඳහා සජීවිකරණය පෙන්වන උපාංග තිරය"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"යතුරු පුවරු පසු ආලෝකය"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"නිවෙස් පාලන"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"තිර සුරැකුමක් ලෙස ඔබේ නිවසේ පාලන වෙත ඉක්මනින් ප්රවේශ වන්න"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"පසුගමනය කරන්න"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"ආපසු යාමට, ස්පර්ශ පුවරුව මත ඇඟිලි තුනකින් වමට හෝ දකුණට ස්වයිප් කරන්න"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"මුල් පිටුවට යාමට, ස්පර්ශ පුවරුව මත ඇඟිලි තුනකින් ඉහළට ස්වයිප් කරන්න"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"මෑත යෙදුම් බැලීමට, ඉහළට ස්වයිප් කර ස්පර්ශ පුවරුව මත ඇඟිලි තුනකින් අල්ලාගෙන සිටින්න"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ඔබේ සියලුම යෙදුම් බැලීමට, ඔබේ යතුරුපුවරුවේ ක්රියාකාරී යතුර ඔබන්න"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"ආපසු යාමට ඔබේ ස්පර්ශ පුවරුව භාවිත කරන්න"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"ඇඟිලි තුනක් භාවිතයෙන් වමට හෝ දකුණට ස්වයිප් කරන්න. තව ඉංගිත දැන ගැනීමට තට්ටු කරන්න."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"මුල් පිටුවට යාමට ඔබේ ස්පර්ශ පුවරුව භාවිත කරන්න"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"ඇඟිලි තුනක් භාවිතයෙන් ඉහළට ස්වයිප් කරන්න. තව ඉංගිත දැන ගැනීමට තට්ටු කරන්න."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"මෑත යෙදුම් බැලීමට ඔබේ ස්පර්ශ පුවරුව භාවිත කරන්න"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"ඇඟිලි තුනක් භාවිතයෙන් ඉහළට ස්වයිප් කර අල්ලාගෙන සිටින්න. තව ඉංගිත දැන ගැනීමට තට්ටු කරන්න."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"සියලුම යෙදුම් බැලීමට ඔබේ යතුරු පුවරුව භාවිත කරන්න"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ඕනෑම අවස්ථාවක ක්රියාකාරී යතුර ඔබන්න. තව ඉංගිත දැන ගැනීමට තට්ටු කරන්න."</string>
</resources>
diff --git a/packages/SystemUI/res/values-si/tiles_states_strings.xml b/packages/SystemUI/res/values-si/tiles_states_strings.xml
index 4bebcc0..681f3d5 100644
--- a/packages/SystemUI/res/values-si/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-si/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"අක්රියයි"</item>
<item msgid="4875147066469902392">"සක්රියයි"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"නොමැත"</item>
- <item msgid="2004750556637773692">"ක්රියාවිරහිතයි"</item>
- <item msgid="8968530753931637871">"ක්රියාත්මකයි"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"නොමැත"</item>
<item msgid="5044688398303285224">"අක්රියයි"</item>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 8c2e2a9..b607739 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -128,13 +128,13 @@
<string name="screenrecord_start_error" msgid="2200660692479682368">"Pri spustení nahrávania obrazovky sa vyskytla chyba"</string>
<string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"Chcete zastaviť nahrávanie?"</string>
<string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"Momentálne nahrávate celú obrazovku"</string>
- <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Momentálne nahrávate <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Momentálne nahrávate aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Zastaviť nahrávanie"</string>
<string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"Zdieľa sa obrazovka"</string>
<string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Chcete prestať zdieľať obrazovku?"</string>
<string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Momentálne zdieľate celú obrazovku s aplikáciou <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string>
<string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Momentálne zdieľate celú obrazovku s aplikáciou"</string>
- <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Momentálne zdieľate <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string>
+ <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Momentálne zdieľate aplikáciu <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string>
<string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"Momentálne zdieľate aplikáciu"</string>
<string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"Prestať zdieľať"</string>
<string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"Prenáša sa obrazovka"</string>
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Výkon"</string>
<string name="user_interface" msgid="3712869377953950887">"Používateľské rozhranie"</string>
<string name="thermal" msgid="6758074791325414831">"Termálne"</string>
+ <string name="custom" msgid="3337456985275158299">"Vlastné"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Nastavenia vlastnej stopy"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Obnoviť predvolené"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Režim jednej ruky"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Načúvacie zariadenia"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktívne"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Režimy priority"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Hotovo"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Nastavenia"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Zapnuté"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Vypnuté"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Nebudú vás vyrušovať zvuky ani vibrácie, iba budíky, pripomenutia, udalosti a volajúci, ktorých určíte. Budete naďalej počuť všetko, čo sa rozhodnete prehrať, ako napríklad hudbu, videá a hry."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Nebudú vás vyrušovať zvuky ani vibrácie, iba budíky. Budete naďalej počuť všetko, čo sa rozhodnete prehrať, ako napríklad hudbu, videá a hry."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa pomaly • Do úplného nabitia zostáva <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> • Nabíja sa • Do úplného nabitia zostáva <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Miniaplikácie na uzamknutej obrazovke"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Potiahnutím doľava spustite komunitný návod"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prispôsobiť"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Zavrieť"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"prepnúť vybranú miniaplikáciu"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Miniaplikácie na uzamknutej obrazovke"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Miniaplikácie na uzamknutej obrazovke uvidia všetci, aj keď je tablet uzamknutý."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"zrušiť výber miniaplikácie"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Miniaplikácie na uzamknutej obrazovke"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Ak chcete otvoriť aplikáciu pomocou miniaplikácie, budete musieť overiť svoju totožnosť. Pamätajte, že si miniaplikáciu môže pozrieť ktokoľvek, aj keď máte tablet uzamknutý. Niektoré miniaplikácie možno nie sú určené pre uzamknutú obrazovku a ich pridanie tu môže byť nebezpečné."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Dobre"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Spustiť"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Žiadne upozornenia"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Žiadne nové upozornenia"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Stlmenie upozornení je zapnuté"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Keď dostanete priveľa upozornení naraz, hlasitosť vášho zariadenia a počet upozornení sa automaticky znížia až na dve minúty."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Vypnúť"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Odomknutím zobrazíte staršie upozornenia"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Toto zariadenie spravuje tvoj rodič"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Vyžaduje sa overenie. Dotknite sa senzora odtlačkov prstov."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Prebiehajúci telefonický hovor"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilné dáta"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Pripojené"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Dočasne pripojené"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Slabé pripojenie"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Hotovo"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Skvelé!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Prejsť späť"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Ak chcete prejsť späť, potiahnite doľava alebo doprava troma prstami kdekoľvek na touchpade."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Tri prsty na touchpade pohybujúce sa doprava a doľava"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Obrazovka zariadenia, na ktorej je animácia gesta späť"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Podsvietenie klávesnice"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Ovládanie domácnosti"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Rýchly prístup k ovládaniu domácnosti z šetriča obrazovky"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Vrátiť späť"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Ak chcete prejsť späť, potiahnite po touchpade troma prstami doľava alebo doprava"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Ak sa chcete vrátiť na plochu, potiahnite po touchpade troma prstami nahor."</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Ak si chcete zobraziť nedávne aplikácie, potiahnite po touchpade troma prstami nahor a pridržte ich."</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Ak si chcete zobraziť všetky aplikácie, stlačte na klávesnici akčný kláves"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Prechádzajte späť pomocou touchpadu"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Potiahnite troma prstami doľava alebo doprava. Viac o gestách sa dozviete klepnutím."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Vráťte sa na plochu pomocou touchpadu"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Potiahnite troma prstami nahor. Viac o gestách sa dozviete klepnutím."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Zobrazte si nedávne aplikácie pomocou touchpadu"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Potiahnite troma prstami nahor a pridržte ich. Viac o gestách sa dozviete klepnutím."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Zobrazte si všetky aplikácie pomocou klávesnice"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Akčný kláves môžete stlačiť kedykoľvek. Viac o gestách sa dozviete klepnutím."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/tiles_states_strings.xml b/packages/SystemUI/res/values-sk/tiles_states_strings.xml
index b0fed02..6b5af80 100644
--- a/packages/SystemUI/res/values-sk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sk/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Vypnuté"</item>
<item msgid="4875147066469902392">"Zapnuté"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Nedostupné"</item>
- <item msgid="2004750556637773692">"Vypnuté"</item>
- <item msgid="8968530753931637871">"Zapnuté"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Nie je k dispozícii"</item>
<item msgid="5044688398303285224">"Vypnuté"</item>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 68117af..69f63b9 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -218,7 +218,7 @@
<string name="biometric_re_enroll_notification_content" msgid="8685925877186288180">"To je potrebno, če želite izboljšati varnost in učinkovitost delovanja."</string>
<string name="fingerprint_re_enroll_notification_title" msgid="4539432429683916604">"Vnovična nastavitev odklepanja s prstnim odtisom"</string>
<string name="fingerprint_re_enroll_notification_name" msgid="630798657797645704">"Odklepanje s prstnim odtisom"</string>
- <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Nastavitev odklepanja s prstnim odtisom"</string>
+ <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Nastavite odklepanje s prstnim odtisom"</string>
<string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"Če želite znova nastaviti odklepanje s prstnim odtisom, bodo trenutne slike in modeli prstnih odtisov izbrisani.\n\nPo izbrisu boste morali znova nastaviti odklepanje s prstnim odtisom, da boste telefon lahko odklenili s prstnim odtisom ali potrdili svojo identiteto."</string>
<string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"Če želite znova nastaviti odklepanje s prstnim odtisom, bodo trenutne slike in model prstnih odtisov izbrisani.\n\nPo izbrisu boste morali znova nastaviti odklepanje s prstnim odtisom, da boste telefon lahko odklenili s prstnim odtisom ali potrdili svojo identiteto."</string>
<string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"Odklepanja s prstnim odtisom ni bilo mogoče nastaviti. Odprite nastavitve in poskusite znova."</string>
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Učinkovitost delovanja"</string>
<string name="user_interface" msgid="3712869377953950887">"Uporabniški vmesnik"</string>
<string name="thermal" msgid="6758074791325414831">"Toplotno"</string>
+ <string name="custom" msgid="3337456985275158299">"Po meri"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Nastavitve sledi po meri"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Obnovi privzeto"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Enoročni način"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Slušni pripomočki"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktivno"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prednostni načini"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Končano"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Nastavitve"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Vklopljeno"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Izklopljeno"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Ne bodo vas motili zvoki ali vibriranje, razen v primeru alarmov, opomnikov, dogodkov in klicateljev, ki jih določite. Še vedno pa boste slišali vse, kar se boste odločili predvajati, vključno z glasbo, videoposnetki in igrami."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Ne bodo vas motili zvoki ali vibriranje, razen v primeru alarmov. Še vedno pa boste slišali vse, kar se boste odločili predvajati, vključno z glasbo, videoposnetki in igrami."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Počasno polnjenje • Napolnjeno čez <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> • Polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Pripomočki na zaklenjenem zaslonu"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Povlecite levo, da zaženete vadnico za skupnost"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prilagodi"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Opusti"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"postavitev izbranega pripomočka"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Pripomočki na zaklenjenem zaslonu"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Pripomočki na zaklenjenem zaslonu so vidni vsem, tudi če je tablica zaklenjena."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"preklic izbire pripomočka"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Pripomočki na zaklenjenem zaslonu"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Če želite aplikacijo odpreti s pripomočkom, morate potrditi, da ste to vi. Upoštevajte tudi, da si jih lahko ogledajo vsi, tudi ko je tablični računalnik zaklenjen. Nekateri pripomočki morda niso predvideni za uporabo na zaklenjenem zaslonu, zato jih tukaj morda ni varno dodati."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Razumem"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Začni zdaj"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Ni obvestil"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Ni novih obvestil"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Utišanje obvestil je vklopljeno"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Ko prejmete preveč obvestil naenkrat, se glasnost naprave in opozoril samodejno zmanjša za največ 2 minuti."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Izklopi"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Odklenite za ogled starejših obvestil"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"To napravo upravlja tvoj starš"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Zahtevano je preverjanje pristnosti. Za preverjanje pristnosti se dotaknite tipala prstnih odtisov."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Poteka klic"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Prenos podatkov v mobilnem omrežju"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Začasno vzpostavljena povezava"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Slaba povezava"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Končano"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Odlično!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Nazaj"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Za pomik nazaj povlecite levo ali desno s tremi prsti kjer koli na sledilni ploščici."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Sledilna ploščica s tremi prsti, ki se premikajo desno in levo"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Zaslon naprave z animacijo, ki prikazuje potezo za pomik nazaj"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Osvetlitev tipkovnice"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrolniki za dom"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Hiter dostop do kontrolnikov za dom na ohranjevalniku zaslona"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Razveljavi"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Za pomik nazaj povlecite s tremi prsti levo ali desno po sledilni ploščici"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Za pomik na začetni zaslon povlecite s tremi prsti navzgor po sledilni ploščici"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Za ogled nedavnih aplikacij povlecite s tremi prsti navzgor po sledilni ploščici in pridržite"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Za ogled vseh aplikacij pritisnite tipko za dejanja na tipkovnici"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Uporaba sledilne ploščice za pomik nazaj"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"S tremi prsti povlecite levo ali desno. Dotaknite se, če želite spoznati več potez."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Uporaba sledilne ploščice za pomik na začetni zaslon"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"S tremi prsti povlecite navzgor. Dotaknite se, če želite spoznati več potez."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Uporaba sledilne ploščice za ogled nedavnih aplikacij"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"S tremi prsti povlecite navzgor in pridržite. Dotaknite se, če želite spoznati več potez."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Uporaba tipkovnice za prikaz vseh aplikacij"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Kadar koli pritisnite tipko za dejanja. Dotaknite se, če želite spoznati več potez."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/tiles_states_strings.xml b/packages/SystemUI/res/values-sl/tiles_states_strings.xml
index e57b87b..5f60ffd 100644
--- a/packages/SystemUI/res/values-sl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sl/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Izklopljeno"</item>
<item msgid="4875147066469902392">"Vklopljeno"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Ni na voljo"</item>
- <item msgid="2004750556637773692">"Izklopljeno"</item>
- <item msgid="8968530753931637871">"Vklopljeno"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Ni na voljo"</item>
<item msgid="5044688398303285224">"Izklopljeno"</item>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index debd441..b26c7d8 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Performanca"</string>
<string name="user_interface" msgid="3712869377953950887">"Ndërfaqja e përdoruesit"</string>
<string name="thermal" msgid="6758074791325414831">"Termike"</string>
+ <string name="custom" msgid="3337456985275158299">"I personalizuar"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Cilësimet e gjurmimit të personalizuar"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Restauro parazgjedhjen"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modaliteti i përdorimit me një dorë"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Pajisje ndihmëse për dëgjimin"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktive"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modalitetet e përparësisë"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"U krye"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Cilësimet"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Aktiv"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Joaktiv"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Nuk do të shqetësohesh nga tingujt dhe dridhjet, përveç alarmeve, alarmeve rikujtuese, ngjarjeve dhe telefonuesve që specifikon. Do të vazhdosh të dëgjosh çdo gjë që zgjedh të luash duke përfshirë muzikën, videot dhe lojërat."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Nuk do të shqetësohesh nga tingujt dhe dridhjet, përveç alarmeve. Do të vazhdosh të dëgjosh çdo gjë që zgjedh të luash duke përfshirë muzikën, videot dhe lojërat."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet ngadalë • Plot për <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> • Po karikohet • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Miniaplikacionet në ekranin e kyçjes"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Rrëshqit shpejt majtas për të filluar udhëzuesin e përbashkët"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizo"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Hiq"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"vendos miniaplikacionin e zgjedhur"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Kyç miniaplikacionet e ekranit"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Çdo person mund të shikojë miniaplikacionet në ekranin tënd të kyçjes, edhe nëse tableti është i kyçur."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"anulo zgjedhjen e miniaplikacionit"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Kyç miniaplikacionet e ekranit"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Për të hapur një aplikacion duke përdorur një miniaplikacion, do të duhet të verifikosh që je ti. Ki parasysh gjithashtu që çdo person mund t\'i shikojë, edhe kur tableti yt është i kyçur. Disa miniaplikacione mund të mos jenë planifikuar për ekranin tënd të kyçjes dhe mund të mos jetë e sigurt t\'i shtosh këtu."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"E kuptova"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Fillo tani"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Asnjë njoftim"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Nuk ka njoftime të reja"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Reduktimi i njoftimeve është aktiv"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Volumi i pajisjes dhe sinjalizimet zvogëlohen automatikisht për deri në 2 minuta kur merr shumë njoftime në të njëjtën kohë."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Çaktivizo"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Shkyç për të parë njoftimet e vjetra"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Kjo pajisje menaxhohet nga prindi yt"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Kërkohet vërtetimi. Prek sensorin e gjurmës së gishtit për t\'u vërtetuar."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonatë në vazhdim"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Të dhënat celulare"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Lidhur"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Lidhur përkohësisht"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Lidhje e dobët"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"U krye"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Punë e shkëlqyer!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Kthehu prapa"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Për t\'u kthyer prapa, rrëshqit shpejt majtas ose djathtas duke përdorur tre gishta kudo në bllokun me prekje."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Blloku me prekje që tregon tre gishta që lëvizin djathtas dhe majtas"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ekrani i pajisjes që tregon një animacion për gjestin e kthimit prapa"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Drita e sfondit e tastierës"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrollet e shtëpisë"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Qasu te kontrollet e shtëpisë si mbrojtës ekrani"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Zhbëj"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Për t\'u kthyer prapa, rrëshqit shpejt majtas ose djathtas me tre gishta në bllokun me prekje"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Për të shkuar tek ekrani bazë, rrëshqit shpejt lart me tre gishta në bllokun me prekje"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Për aplikacionet e fundit, rrëshqit shpejt lart dhe mbaj shtypur me tre gishta në bllokun me prekje"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Për të shikuar të gjitha aplikacionet, shtyp tastin e veprimit në tastierë"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Përdor bllokun me prekje për t\'u kthyer prapa"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Rrëshqit shpejt majtas ose djathtas duke përdorur tre gishta. Trokit për të mësuar më shumë gjeste."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Përdor bllokun me prekje për të shkuar tek ekrani bazë"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Rrëshqit shpejt lart duke përdorur tre gishta. Trokit për të mësuar më shumë gjeste."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Përdor bllokun me prekje për të shikuar aplikacionet e fundit"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Rrëshqit shpejt lart dhe mbaj shtypur me tre gishta. Trokit për të mësuar më shumë gjeste."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Përdor tastierën për të shikuar të gjitha aplikacionet"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Shtyp tastin e veprimit në çdo kohë. Trokit për të mësuar më shumë gjeste."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sq/tiles_states_strings.xml b/packages/SystemUI/res/values-sq/tiles_states_strings.xml
index 126d0dc..9b5032e 100644
--- a/packages/SystemUI/res/values-sq/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sq/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Joaktiv"</item>
<item msgid="4875147066469902392">"Aktiv"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Nuk ofrohet"</item>
- <item msgid="2004750556637773692">"Joaktiv"</item>
- <item msgid="8968530753931637871">"Aktiv"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Nuk ofrohet"</item>
<item msgid="5044688398303285224">"Joaktiv"</item>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 8dccb44..7acfbf5 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -141,7 +141,7 @@
<string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Желите да зауставите пребацивање?"</string>
<string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Тренутно пребацујете цео екран на: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Тренутно пребацујете цео екран на уређај у близини"</string>
- <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> се тренутно пребацује на: <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> тренутно пребацујете на: <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
<string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> се тренутно пребацује на уређај у близини"</string>
<string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"Тренутно пребацујете на: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"Тренутно пребацујете на уређај у близини"</string>
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Перформансе"</string>
<string name="user_interface" msgid="3712869377953950887">"Кориснички интерфејс"</string>
<string name="thermal" msgid="6758074791325414831">"Термална камера"</string>
+ <string name="custom" msgid="3337456985275158299">"Прилагођено"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Подешавања прилагођеног праћења"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Врати подразумевано"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Режим једном руком"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слушни апарати"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Активно"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Приоритетни режими"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Готово"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Подешавања"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Укључено"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Искључено"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Неће вас узнемиравати звукови и вибрације осим за аларме, подсетнике, догађаје и позиваоце које наведете. И даље ћете чути све што одаберете да пустите, укључујући музику, видео снимке и игре."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Неће вас узнемиравати звукови и вибрације осим за аларме. И даље ћете чути све што одаберете да пустите, укључујући музику, видео снимке и игре."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Споро се пуни • <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> • Пуни се • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до краја пуњења"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Виџети на закључаном екрану"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Превуците улево да бисте започели заједнички водич"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Прилагодите"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Одбаци"</string>
@@ -498,9 +507,8 @@
<string name="accessibility_action_label_remove_widget" msgid="3373779447448758070">"уклоните виџет"</string>
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"поставите изабрани виџет"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Виџети за закључани екран"</string>
- <string name="communal_widget_picker_description" msgid="490515450110487871">"Сви могу да виде веџете на закључаном екрану, чак и када је таблет закључан."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="communal_widget_picker_description" msgid="490515450110487871">"Сви могу да виде виџете на закључаном екрану, чак и када је таблет закључан."</string>
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"поништи избор виџета"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Виџети за закључани екран"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Да бисте отворили апликацију која користи виџет, треба да потврдите да сте то ви. Имајте у виду да свако може да га види, чак и када је таблет закључан. Неки виџети можда нису намењени за закључани екран и можда није безбедно да их тамо додате."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Важи"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Започни"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Нема обавештења"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Нема нових обавештења"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Утишавање обавештења је укључено"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Звук и број упозорења на уређају се аутоматски смањују на 2 минута када добијете превише обавештења."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Искључи"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Откључајте за старија обавештења"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Овим уређајем управља родитељ"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Потребна је потврда идентитета. Додирните сензор за отисак прста да бисте потврдили идентитет."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Актуелни телефонски позив"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилни подаци"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Повезано"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Привремено повезано"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Веза је лоша"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Одлично!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Да бисте се вратили, превуците улево или удесно са три прста било где на тачпеду."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Тачпед са приказом три прста који се померају удесно и улево"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Екран уређаја са приказом анимације покрета за назад"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Позадинско осветљење тастатуре"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Контроле за дом"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Брз приступ контролама за дом као чувару екрана"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Опозови"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Да бисте се вратили, превуците улево или удесно са три прста на тачпеду"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Да бисте отишли на почетни екран, превуците нагоре са три прста на тачпеду"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Да бисте прегледали недавне апликације, превуците нагоре и задржите са три прста на тачпеду"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Да бисте погледали све апликације, притисните тастер радњи на тастатури"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Користите тачпед да бисте се вратили"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Превуците улево или удесно са три прста. Додирните да бисте видели више покрета."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Користите тачпед да бисте отишли на почетни екран"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Превуците нагоре са три прста. Додирните да бисте видели више покрета."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Користите тачпед да бисте прегледали недавне апликације"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Превуците нагоре и задржите са три прста. Додирните да бисте видели више покрета."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Користите тастатуру да бисте прегледали све апликације"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Притисните тастер радњи у било ком тренутку. Додирните да бисте видели више покрета."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/tiles_states_strings.xml b/packages/SystemUI/res/values-sr/tiles_states_strings.xml
index ab05c21..2acf1d2 100644
--- a/packages/SystemUI/res/values-sr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sr/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Искључено"</item>
<item msgid="4875147066469902392">"Укључено"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Недоступно"</item>
- <item msgid="2004750556637773692">"Искључено"</item>
- <item msgid="8968530753931637871">"Укључено"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Недоступно"</item>
<item msgid="5044688398303285224">"Искључено"</item>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 3b65365..b632dde 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Prestanda"</string>
<string name="user_interface" msgid="3712869377953950887">"Användargränssnitt"</string>
<string name="thermal" msgid="6758074791325414831">"Termisk"</string>
+ <string name="custom" msgid="3337456985275158299">"Anpassat"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Anpassade spårningsinställningar"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Återställ standardinställning"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Enhandsläge"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hörhjälpmedel"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktiva"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioriterade lägen"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Klar"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Inställningar"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"På"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Av"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Du blir inte störd av ljud och vibrationer, förutom från alarm, påminnelser, händelser och specifika samtal. Ljudet är fortfarande på för sådant du väljer att spela upp, till exempel musik, videor och spel."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Du blir inte störd av ljud och vibrationer, förutom från alarm. Ljudet är fortfarande på för sådant du väljer att spela upp, till exempel musik, videor och spel."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas långsamt • Fulladdat om <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> • Laddas • Fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgetar på låsskärmen"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Svep åt vänster för att börja med gruppguiden"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Anpassa"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Ignorera"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"placera vald widget"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgetar för låsskärm"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Vem som helst kan se widgetar på din låsskärm, även om surfplattan är låst."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"avmarkera widget"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgetar för låsskärm"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Du måste verifiera din identitet innan du öppnar en app med en widget. Tänk också på att alla kan se dem, även när surfplattan är låst. Vissa widgetar kanske inte är avsedda för låsskärmen och det kan vara osäkert att lägga till dem här."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Starta nu"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Inga aviseringar"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Det finns inga nya aviseringar"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Gradvis sänkning för aviseringar är på"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Enheten sänker volymen och minimerar aviseringar i upp till två minuter när du får för många aviseringar samtidigt."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Inaktivera"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Lås upp för att se äldre aviseringar"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Den här enheten hanteras av din förälder"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentisering krävs. Identifiera dig genom att trycka på fingeravtryckssensorn."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Pågående samtal"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobildata"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Ansluten"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tillfälligt ansluten"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Dålig anslutning"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Klar"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Bra jobbat!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Tillbaka"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Gå tillbaka genom att svepa åt vänster eller höger med tre fingrar var som helst på styrplattan."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Tre fingrar rör sig åt höger och vänster på en styrplatta"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"En enhetsskärm visar en animation för rörelsen Tillbaka"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Bakgrundsbelysning för tangentbord"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Hemstyrning"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Kom snabbt åt hemstyrningen via skärmsläckaren"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Ångra"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Svep åt höger eller vänster på styrplattan med tre fingrar för att gå tillbaka"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Svep uppåt på styrplattan med tre fingrar för att gå till startskärmen"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Svep uppåt på styrplattan med tre fingrar och håll kvar för att se nyligen använda appar"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Tryck på åtgärdstangenten på tangentbordet för att se alla appar"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Använd styrplattan för att gå tillbaka"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Svep åt vänster eller höger med tre fingrar. Tryck för att lära dig fler rörelser."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Använd styrplattan för att gå till startskärmen"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Svep uppåt med tre fingrar. Tryck för att lära dig fler rörelser."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Använd styrplattan för att se nyligen använda appar"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Svep uppåt med tre fingrar och håll kvar. Tryck för att lära dig fler rörelser."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Använd tangentbordet för att se alla appar"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Tryck på åtgärdstangenten när som helst. Tryck för att lära dig fler rörelser."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/tiles_states_strings.xml b/packages/SystemUI/res/values-sv/tiles_states_strings.xml
index ba740d5..cf49f8d 100644
--- a/packages/SystemUI/res/values-sv/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sv/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Av"</item>
<item msgid="4875147066469902392">"På"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Inte tillgängliga"</item>
- <item msgid="2004750556637773692">"Av"</item>
- <item msgid="8968530753931637871">"På"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Inte tillgängligt"</item>
<item msgid="5044688398303285224">"Av"</item>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index faaa1c4..d3e4e5d 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -132,17 +132,17 @@
<string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Acha kurekodi"</string>
<string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"Inaruhusu ufikiaji kwenye skrini"</string>
<string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Ungependa kuacha kuonyesha skrini?"</string>
- <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Kwa sasa unatuma skrini yako nzima kwenye <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string>
- <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Kwa sasa unatuma skrini yako nzima kwenye programu"</string>
- <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Kwa sasa unatuma <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string>
- <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"Kwa sasa unatuma programu"</string>
+ <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Kwa sasa unatuma maudhui yaliyo katika skrini yako nzima kwenye <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string>
+ <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Kwa sasa unatuma maudhui yaliyo katika skrini yako nzima kwenye programu"</string>
+ <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Kwa sasa unatumia <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> pamoja na wengine"</string>
+ <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"Kwa sasa unatumia programu pamoja na wengine"</string>
<string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"Acha kuonyesha skrini"</string>
<string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"Inatuma skrini"</string>
<string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Ungependa kuacha kutuma?"</string>
- <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Kwa sasa unatuma skrini yako nzima kwenye <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
- <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Kwa sasa unatuma skrini yako nzima kwenye kifaa kilicho karibu"</string>
- <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Kwa sasa unatuma <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> kwenye <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
- <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"Kwa sasa unatuma <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> kwenye kifaa kilicho karibu"</string>
+ <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Kwa sasa unatuma maudhui yaliyo katika skrini yako nzima kwenye <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Kwa sasa unatuma maudhui yaliyo katika skrini yako nzima kwenye kifaa kilicho karibu"</string>
+ <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Kwa sasa unatuma maudhui yaliyo katika <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> kwenye <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"Kwa sasa unatuma maudhui yaliyo katika <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> kwenye kifaa kilicho karibu"</string>
<string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"Kwa sasa unatuma maudhui kwenye <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"Kwa sasa unatuma maudhui kwenye kifaa kilicho karibu"</string>
<string name="cast_to_other_device_stop_dialog_button" msgid="6420183747435521834">"Acha kutuma maudhui"</string>
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Utendaji"</string>
<string name="user_interface" msgid="3712869377953950887">"Kiolesura"</string>
<string name="thermal" msgid="6758074791325414831">"Joto"</string>
+ <string name="custom" msgid="3337456985275158299">"Maalum"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Mipangilio Maalum ya Historia ya Shughuli"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Rejesha Mipangilio Chaguomsingi"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Hali ya kutumia kwa mkono mmoja"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Vifaa vya kusikilizia"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Vimeunganishwa"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Hali za kipaumbele"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Nimemaliza"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Mipangilio"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Imewashwa"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Imezimwa"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Hutasumbuliwa na sauti na mitetemo, isipokuwa kengele, vikumbusho, matukio na simu zinazopigwa na watu uliobainisha. Bado utasikia chochote utakachochagua kucheza, ikiwa ni pamoja na muziki, video na michezo."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Hutasumbuliwa na sauti na mitetemo, isipokuwa kengele. Bado utasikia chochote utakachochagua kucheza, ikiwa ni pamoja na muziki, video na michezo."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji polepole • Itajaa baada ya <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> • Inachaji • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Wijeti kwenye skrini iliyofungwa"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Telezesha kidole kushoto ili uanze mafunzo ya pamoja"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Weka mapendeleo"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Funga"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"weka wijeti uliyochagua"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Wijeti zinazoonekana kwenye skrini iliyofungwa"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Yeyote anaweza kuona wijeti kwenye skrini yako iliyofungwa, hata ikiwa umefunga kishikwambi chako."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"acha kuchagua wijeti"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Wijeti zinazoonekana kwenye skrini iliyofungwa"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Utahitaji kuthibitisha kuwa ni wewe ili ufungue programu ukitumia wijeti. Pia, kumbuka kuwa mtu yeyote anaweza kuziona, hata kishikwambi chako kikiwa kimefungwa. Huenda baadhi ya wijeti hazikukusudiwa kutumika kwenye skrini yako iliyofungwa na huenda si salama kuziweka hapa."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Nimeelewa"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Anza sasa"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Hakuna arifa"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Hakuna arifa mpya"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Umewasha mipangilio ya kutuliza arifa"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Arifa na sauti hupunguzwa kiotomatiki kwenye kifaa chako kwa hadi dakika 2 unapopokea arifa nyingi kwa wakati mmoja."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Zima"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Fungua ili uone arifa za zamani"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Kifaa hiki kinadhibitiwa na mzazi wako"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Uthibitishaji unahitajika. Gusa kitambua alama ya kidole ili uthibitishe."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Simu inayoendelea"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Data ya mtandao wa simu"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Imeunganishwa"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Imeunganishwa kwa muda"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Muunganisho duni"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Nimemaliza"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Kazi nzuri!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Rudi nyuma"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Ili kurudi nyuma, telezesha vidole vitatu kushoto au kulia mahali popote kwenye padi ya kugusa."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Padi ya kugusa inayoonyesha vidole vitatu vikisonga kulia na kushoto"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Skrini ya kifaa inayoonyesha uhuishaji wa mguso wa nyuma"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Mwanga chini ya kibodi"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Dhibiti Vifaa Nyumbani"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Fikia haraka vidhibiti vya vifaa nyumbani vikiwa taswira ya skrini"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Tendua"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Telezesha vidole vitatu kutoka kushoto au kulia kwenye padi ya kugusa ili urudi nyuma"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Telezesha vidole vitatu juu kwenye padi ya kugusa ili urudi kwenye skrini ya kwanza"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Telezesha vidole vitatu juu na ushikilie kwenye padi ya kugusa ili uangalie programu za hivi majuzi"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Bonyeza kitufe cha vitendo kwenye kibodi yako ili uangalie programu zako zote"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Kutumia padi yako ya kugusa ili kurudi nyuma"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Telezesha vidole vitatu kulia au kushoto. Gusa ili upate maelezo kuhusu miguso zaidi."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Kutumia padi yako ya kugusa ili kurudi kwenye skrini ya kwanza"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Telezesha vidole vitatu juu. Gusa ili upate maelezo kuhusu miguso zaidi."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Kutumia padi yako ya kugusa ili kuangalia programu za hivi majuzi"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Telezesha vidole vitatu juu na ushikilie. Gusa ili upate maelezo kuhusu miguso zaidi."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Kutumia kibodi yako kuangalia programu zote"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Bonyeza kitufe cha vitendo wakati wowote. Gusa ili upate maelezo kuhusu miguso zaidi."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/tiles_states_strings.xml b/packages/SystemUI/res/values-sw/tiles_states_strings.xml
index 369d56a..15de7f8 100644
--- a/packages/SystemUI/res/values-sw/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sw/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Kimezimwa"</item>
<item msgid="4875147066469902392">"Kimewashwa"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Haipatikani"</item>
- <item msgid="2004750556637773692">"Imezimwa"</item>
- <item msgid="8968530753931637871">"Imewashwa"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Hakipatikani"</item>
<item msgid="5044688398303285224">"Kimezimwa"</item>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 414d0a7..6cef518 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"செயல்திறன்"</string>
<string name="user_interface" msgid="3712869377953950887">"பயனர் இடைமுகம்"</string>
<string name="thermal" msgid="6758074791325414831">"தெர்மல்"</string>
+ <string name="custom" msgid="3337456985275158299">"பிரத்தியேகம்"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"பிரத்தியேக டிரேஸ் அமைப்புகள்"</string>
+ <string name="restore_default" msgid="5259420807486239755">"இயல்புக்கு மீட்டெடு"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ஒற்றைக் கைப் பயன்முறை"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"செவித்துணைக் கருவிகள்"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"செயலில் உள்ளது"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"முன்னுரிமைப் பயன்முறைகள்"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"முடிந்தது"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"அமைப்புகள்"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"இயக்கப்பட்டுள்ளது"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"முடக்கப்பட்டுள்ளது"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"அலாரங்கள், நினைவூட்டல்கள், நிகழ்வுகள் மற்றும் குறிப்பிட்ட அழைப்பாளர்களைத் தவிர்த்து, பிற ஒலிகள் மற்றும் அதிர்வுகளின் தொந்தரவு இருக்காது. எனினும், நீங்கள் எதையேனும் (இசை, வீடியோக்கள், கேம்ஸ் போன்றவை) ஒலிக்கும்படி தேர்ந்தெடுத்திருந்தால், அவை வழக்கம் போல் ஒலிக்கும்."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"அலாரங்களைத் தவிர்த்து, பிற ஒலிகள் மற்றும் அதிர்வுகளின் தொந்தரவு இருக்காது. எனினும், நீங்கள் எதையேனும் (இசை, வீடியோக்கள், கேம்ஸ் போன்றவை) ஒலிக்கும்படி தேர்ந்தெடுத்திருந்தால், அவை வழக்கம் போல் ஒலிக்கும்."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • மெதுவாக சார்ஜாகிறது • <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> • சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுவதும் சார்ஜாகும்"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"பூட்டுத் திரையில் விட்ஜெட்கள்"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"சமூகப் பயிற்சியைத் தொடங்க இடதுபுறம் ஸ்வைப் செய்யுங்கள்"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"பிரத்தியேகமாக்குங்கள்"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"மூடுக"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"தேர்ந்தெடுத்த விட்ஜெட்டைக் காட்சிப்படுத்தும்"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"பூட்டுத் திரை விட்ஜெட்கள்"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"டேப்லெட் பூட்டப்பட்டிருந்தாலும் பூட்டுத் திரையில் விட்ஜெட்டை எவரும் பார்க்கலாம்."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"விட்ஜெட்டைத் தேர்வுநீக்கும்"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"பூட்டுத் திரை விட்ஜெட்கள்"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"விட்ஜெட்டைப் பயன்படுத்தி ஆப்ஸைத் திறக்க, அது நீங்கள்தான் என்பதை உறுதிசெய்ய வேண்டும். அத்துடன், உங்கள் டேப்லெட் பூட்டப்பட்டிருந்தாலும்கூட அவற்றை யார் வேண்டுமானாலும் பார்க்கலாம் என்பதை நினைவில்கொள்ளுங்கள். சில விட்ஜெட்கள் உங்கள் பூட்டுத் திரைக்காக உருவாக்கப்பட்டவை அல்ல என்பதையும் அவற்றை இங்கே சேர்ப்பது பாதுகாப்பற்றதாக இருக்கக்கூடும் என்பதையும் நினைவில்கொள்ளுங்கள்."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"சரி"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"இப்போது தொடங்கு"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"அறிவிப்புகள் இல்லை"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"புதிய அறிவிப்புகள் இல்லை"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"\'குறைந்த ஒலியளவில் அறிவிப்புகள்\' இயக்கப்பட்டுள்ளது"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"ஒரே நேரம் பல அறிவிப்புகள் வரும்போது சாதன ஒலியளவும் விழிப்பூட்டலும் தானாக 2 நிமிடம் குறைக்கப்படும்."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"முடக்கு"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"பழைய அறிவிப்பைப் பார்க்க அன்லாக் செய்க"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"இந்தச் சாதனம் உங்கள் பெற்றோரால் நிர்வகிக்கப்படுகிறது"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"அங்கீகாரம் தேவை. கைரேகை சென்சாரைத் தொட்டு அங்கீகரியுங்கள்."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"செயலில் உள்ள மொபைல் அழைப்பு"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"மொபைல் டேட்டா"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"இணைக்கப்பட்டது"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"தற்காலிகமாக இணைக்கப்பட்டுள்ளது"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"இணைப்பு மோசமாக உள்ளது"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"முடிந்தது"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"அருமை!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"பின்செல்"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"பின்செல்ல, உங்கள் டச்பேடில் எங்கு வேண்டுமானாலும் இடது அல்லது வலதுபுறமாக மூன்று விரல்களால் ஸ்வைப் செய்யவும்."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"மூன்று விரல்கள் வலது மற்றும் இடதுபுறம் நகர்வதை டச்பேட் காட்டுகிறது"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"பின்செல்லும் சைகைக்கான அனிமேஷனை சாதனத்தின் திரை காட்டுகிறது"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"கீபோர்டு பேக்லைட்"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"ஹோம் கன்ட்ரோல்கள்"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"ஹோம் கன்ட்ரோல்களை ஸ்கிரீன் சேவராக அணுகலாம்"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"செயல்தவிர்"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"பின்செல்ல, உங்கள் டச்பேடில் இடது அல்லது வலதுபுறமாக மூன்று விரல்களால் ஸ்வைப் செய்யவும்"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"முகப்புக்குச் செல்ல, உங்கள் டச்பேடில் மூன்று விரல்களால் மேல்நோக்கி ஸ்வைப் செய்யவும்"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"சமீபத்திய ஆப்ஸைப் பார்க்க, டச்பேடில் மூன்று விரல்களால் மேல்நோக்கி ஸ்வைப் செய்து பிடிக்கவும்"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"அனைத்து ஆப்ஸையும் பார்க்க, உங்கள் கீபோர்டில் உள்ள ஆக்ஷன் பட்டனை அழுத்தவும்"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"பின்செல்ல, உங்கள் டச்பேடைப் பயன்படுத்துங்கள்"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"மூன்று விரல்களால் இடது அல்லது வலதுபுறம் ஸ்வைப் செய்யவும். சைகைகள் குறித்து மேலும் அறிய தட்டவும்."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"முகப்புக்குச் செல்ல, உங்கள் டச்பேடைப் பயன்படுத்துங்கள்"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"மூன்று விரல்களால் மேல்நோக்கி ஸ்வைப் செய்யவும். சைகைகள் குறித்து மேலும் அறிய தட்டவும்."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"சமீபத்திய ஆப்ஸைப் பார்க்க, உங்கள் டச்பேடைப் பயன்படுத்துங்கள்"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"மூன்று விரல்களால் மேல்நோக்கி ஸ்வைப் செய்து பிடிக்கவும். சைகைகள் குறித்து மேலும் அறிய தட்டவும்."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"அனைத்து ஆப்ஸையும் பார்க்க உங்கள் கீபோர்டைப் பயன்படுத்துங்கள்"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"எப்போது வேண்டுமானாலும் ஆக்ஷன் பட்டனை அழுத்தலாம். சைகைகள் குறித்து மேலும் அறிய தட்டவும்."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ta/tiles_states_strings.xml b/packages/SystemUI/res/values-ta/tiles_states_strings.xml
index 9f23d0a..a3b9538 100644
--- a/packages/SystemUI/res/values-ta/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ta/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"முடக்கப்பட்டுள்ளது"</item>
<item msgid="4875147066469902392">"இயக்கப்பட்டுள்ளது"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"இல்லை"</item>
- <item msgid="2004750556637773692">"முடக்கப்பட்டுள்ளது"</item>
- <item msgid="8968530753931637871">"இயக்கப்பட்டுள்ளது"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"கிடைக்கவில்லை"</item>
<item msgid="5044688398303285224">"முடக்கப்பட்டுள்ளது"</item>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 1b1d608..e9cb6eb 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"పనితీరు"</string>
<string name="user_interface" msgid="3712869377953950887">"యూజర్ ఇంటర్ఫేస్"</string>
<string name="thermal" msgid="6758074791325414831">"థర్మల్"</string>
+ <string name="custom" msgid="3337456985275158299">"అనుకూలంగా మార్చుకోండి"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"కస్టమ్ ట్రేస్ సెట్టింగ్లు"</string>
+ <string name="restore_default" msgid="5259420807486239755">"డిఫాల్ట్ను రీస్టోర్ చేయండి"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"వన్-హ్యాండెడ్ మోడ్"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"వినికిడి పరికరాలు"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"యాక్టివ్"</string>
@@ -429,10 +432,11 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"ముఖ్యమైన ఫైళ్ల మోడ్స్"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"పూర్తయింది"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"సెట్టింగ్లు"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
- <skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
- <skip />
+ <string name="zen_mode_on" msgid="9085304934016242591">"ఆన్లో ఉంది"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"ఆఫ్లో ఉంది"</string>
+ <string name="zen_mode_set_up" msgid="7457957033034460064">"సెటప్ చేయండి"</string>
+ <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"సెట్టింగ్లలో మేనేజ్ చేయండి"</string>
+ <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{మోడ్స్ ఏవీ యాక్టివ్గా లేవు}=1{{mode} యాక్టివ్గా ఉంది}other{# మోడ్స్ యాక్టివ్గా ఉన్నాయి}}"</string>
<string name="zen_priority_introduction" msgid="3159291973383796646">"మీరు పేర్కొనే అలారాలు, రిమైండర్లు, ఈవెంట్లు మరియు కాలర్ల నుండి మినహా మరే ఇతర ధ్వనులు మరియు వైబ్రేషన్లతో మీకు అంతరాయం కలగదు. మీరు ఇప్పటికీ సంగీతం, వీడియోలు మరియు గేమ్లతో సహా మీరు ప్లే చేయడానికి ఎంచుకున్నవి ఏవైనా వింటారు."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"అలారాలు నుండి మినహా మరే ఇతర ధ్వనులు మరియు వైబ్రేషన్లతో మీకు అంతరాయం కలగదు. మీరు ఇప్పటికీ సంగీతం, వీడియోలు మరియు గేమ్లతో సహా మీరు ప్లే చేయడానికి ఎంచుకున్నవి ఏవైనా వింటారు."</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"అనుకూలంగా మార్చండి"</string>
@@ -471,6 +475,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • నెమ్మదిగా ఛార్జ్ అవుతోంది • <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> • ఛార్జ్ అవుతోంది • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"లాక్ స్క్రీన్లో విడ్జెట్లు"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"కమ్యూనల్ ట్యుటోరియల్ను ప్రారంభించడానికి ఎడమ వైపునకు స్వైప్ చేయండి"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"అనుకూలంగా మార్చండి"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"విస్మరించండి"</string>
@@ -499,8 +505,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"ఎంచుకున్న విడ్జెట్ కోసం ప్లేస్ను ఎంచుకోండి"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"లాక్ స్క్రీన్ విడ్జెట్లు"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"మీ టాబ్లెట్ లాక్ చేసి ఉన్నా, మీ లాక్ స్క్రీన్లో విడ్జెట్లను ఎవరైనా చూడవచ్చు."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"విడ్జెట్ ఎంపిక రద్దు చేయండి"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"లాక్ స్క్రీన్ విడ్జెట్లు"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"విడ్జెట్ను ఉపయోగించి యాప్ను తెరవడానికి, ఇది మీరేనని వెరిఫై చేయాల్సి ఉంటుంది. అలాగే, మీ టాబ్లెట్ లాక్ చేసి ఉన్నప్పటికీ, ఎవరైనా వాటిని చూడగలరని గుర్తుంచుకోండి. కొన్ని విడ్జెట్లు మీ లాక్ స్క్రీన్కు తగినవి కాకపోవచ్చు, వాటిని ఇక్కడ జోడించడం సురక్షితం కాకపోవచ్చు."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"అర్థమైంది"</string>
@@ -557,10 +562,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"ఇప్పుడే ప్రారంభించండి"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"నోటిఫికేషన్లు లేవు"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"కొత్త నోటిఫికేషన్లు ఏవీ లేవు"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"నోటిఫికేషన్ కూల్డౌన్ ఆన్ అయింది"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"ఒకేసారి పలు నోటిఫికేషన్లు వస్తే, పరికర వాల్యూమ్, అలర్ట్లు ఆటోమేటిక్గా 2 నిమిషాలకు తగ్గించబడతాయి."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"ఆఫ్ చేయండి"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"పాత నోటిఫికేషన్ల కోసం అన్లాక్ చేయండి"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ఈ పరికరాన్ని మీ తల్లి/తండ్రి మేనేజ్ చేస్తున్నారు"</string>
@@ -1226,7 +1229,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ప్రామాణీకరణ అవసరం. ప్రామాణీకరించడానికి వేలిముద్ర సెన్సార్ను తాకండి."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ఫోన్ కాల్ జరుగుతోంది"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"మొబైల్ డేటా"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"కనెక్ట్ చేయబడింది"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"తాత్కాలికంగా కనెక్ట్ చేయబడింది"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"కనెక్షన్ బాగాలేదు"</string>
@@ -1380,7 +1382,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"పూర్తయింది"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"విజయవంతమైంది!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"వెనుకకు"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"వెనుకకు వెళ్లడానికి, టచ్ప్యాడ్లో ఎక్కడైనా మూడు వేళ్లను ఉపయోగించి ఎడమ లేదా కుడికి స్వైప్ చేయండి."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"మూడు వేళ్లు కుడి, ఎడమకు కదులుతున్నట్లు చూపే టచ్ప్యాడ్"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"వెనుక సంజ్ఞ కోసం యానిమేషన్ను చూపుతున్న పరికర స్క్రీన్"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"కీబోర్డ్ బ్యాక్లైట్"</string>
@@ -1388,28 +1393,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"హోమ్ కంట్రోల్స్"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"హోమ్ కంట్రోల్స్ను స్క్రీన్ సేవర్గా చేసి వేగంగా యాక్సెస్ పొందండి"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"చర్య రద్దు చేయండి"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"వెనుకకు వెళ్లడానికి, టచ్ప్యాడ్లో మూడు వేళ్లను ఉపయోగించి ఎడమ లేదా కుడి వైపునకు స్వైప్ చేయండి"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"హోమ్కు వెళ్లడానికి, టచ్ప్యాడ్లో మీ మూడు వెళ్లతో పైకి స్వైప్ చేయండి"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"ఇటీవలి యాప్లను చూడటానికి, టచ్ప్యాడ్లో మూడు వేళ్లతో పైకి స్వైప్ చేసి, హోల్డ్ చేయండి"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"మీ యాప్లన్నింటినీ చూడటానికి, మీ కీబోర్డ్లో యాక్షన్ కీని నొక్కండి"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"వెనుకకు వెళ్లడానికి మీ టచ్ప్యాడ్ను ఉపయోగించండి"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"మూడు వేళ్లతో ఎడమ / కుడి వైపునకు స్వైప్ చేయండి. మరిన్ని సంజ్ఞల గురించి తెలుసుకోవడానికి ట్యాప్ చేయండి."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"హోమ్కు వెళ్లడానికి మీ టచ్ప్యాడ్ను ఉపయోగించండి"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"మూడు వేళ్లను ఉపయోగించి పైకి స్వైప్ చేయండి. మరిన్ని సంజ్ఞల గురించి తెలుసుకోవడానికి ట్యాప్ చేయండి."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"ఇటీవలి యాప్లను చూడటానికి మీ టచ్ప్యాడ్ను ఉపయోగించండి"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"మూడు వేళ్లతో పైకి స్వైప్ చేసి, హోల్డ్ చేయండి. మరిన్ని సంజ్ఞల గురించి తెలుసుకోవడానికి ట్యాప్ చేయండి."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"యాప్లన్నింటినీ చూడటానికి మీ కీబోర్డ్ను ఉపయోగించండి"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ఏ సమయంలోనైనా యాక్షన్ కీని నొక్కండి. మరిన్ని సంజ్ఞల గురించి తెలుసుకోవడానికి ట్యాప్ చేయండి."</string>
</resources>
diff --git a/packages/SystemUI/res/values-te/tiles_states_strings.xml b/packages/SystemUI/res/values-te/tiles_states_strings.xml
index 1f70f85..6584cdd 100644
--- a/packages/SystemUI/res/values-te/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-te/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"ఆఫ్లో ఉంది"</item>
<item msgid="4875147066469902392">"ఆన్లో ఉంది"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"అందుబాటులో లేదు"</item>
- <item msgid="2004750556637773692">"ఆఫ్లో ఉంది"</item>
- <item msgid="8968530753931637871">"ఆన్లో ఉంది"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"అందుబాటులో లేదు"</item>
<item msgid="5044688398303285224">"ఆఫ్లో ఉంది"</item>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index c4e2334..0d131ac 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -126,7 +126,7 @@
<string name="screenrecord_save_text" msgid="3008973099800840163">"แตะเพื่อดู"</string>
<string name="screenrecord_save_error" msgid="5862648532560118815">"เกิดข้อผิดพลาดในการบันทึกหน้าจอ"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"เกิดข้อผิดพลาดขณะเริ่มบันทึกหน้าจอ"</string>
- <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"หยุดบันทึกใช่ไหม"</string>
+ <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"หยุดบันทึกไหม"</string>
<string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"คุณกำลังบันทึกทั้งหน้าจอ"</string>
<string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"คุณกำลังบันทึก <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"หยุดบันทึก"</string>
@@ -138,7 +138,7 @@
<string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"คุณกำลังแชร์แอป"</string>
<string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"หยุดแชร์"</string>
<string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"กำลังแคสต์หน้าจอ"</string>
- <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"หยุดการแคสต์ไหม"</string>
+ <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"หยุดแคสต์ไหม"</string>
<string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"คุณกำลังแคสต์ทั้งหน้าจอไปยัง <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"คุณกำลังแคสต์ทั้งหน้าจอไปยังอุปกรณ์ที่อยู่ใกล้เคียง"</string>
<string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"คุณกำลังแคสต์ <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> ไปยัง <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"ประสิทธิภาพ"</string>
<string name="user_interface" msgid="3712869377953950887">"อินเทอร์เฟซผู้ใช้"</string>
<string name="thermal" msgid="6758074791325414831">"ความร้อน"</string>
+ <string name="custom" msgid="3337456985275158299">"กำหนดเอง"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"การตั้งค่าการติดตามแบบกำหนดเอง"</string>
+ <string name="restore_default" msgid="5259420807486239755">"คืนค่าเริ่มต้น"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"โหมดมือเดียว"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"เครื่องช่วยฟัง"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"ใช้งานอยู่"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"โหมดสำคัญ"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"เสร็จสิ้น"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"การตั้งค่า"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"เปิด"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"ปิด"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"คุณจะไม่ถูกรบกวนจากเสียงและการสั่น ยกเว้นเสียงนาฬิกาปลุก การช่วยเตือน กิจกรรม และผู้โทรที่ระบุไว้ คุณจะยังคงได้ยินสิ่งที่คุณเลือกเล่น เช่น เพลง วิดีโอ และเกม"</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"คุณจะไม่ถูกรบกวนจากเสียงและการสั่น ยกเว้นเสียงนาฬิกาปลุก คุณจะยังคงได้ยินสิ่งที่คุณเลือกเล่น เช่น เพลง วิดีโอ และเกม"</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จอย่างช้าๆ • จะเต็มในอีก <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> • กำลังชาร์จ • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"วิดเจ็ตในหน้าจอล็อก"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ปัดไปทางซ้ายเพื่อเริ่มบทแนะนำส่วนกลาง"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ปรับแต่ง"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ปิด"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"จัดวางวิดเจ็ตที่เลือก"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"วิดเจ็ตในหน้าจอล็อก"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"ทุกคนจะดูวิดเจ็ตที่อยู่ในหน้าจอล็อกของคุณได้ แม้ว่าแท็บเล็ตจะล็อกอยู่ก็ตาม"</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ยกเลิกการเลือกวิดเจ็ต"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"วิดเจ็ตในหน้าจอล็อก"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"หากต้องการเปิดแอปโดยใช้วิดเจ็ต คุณจะต้องยืนยันตัวตนของคุณ นอกจากนี้ โปรดทราบว่าผู้อื่นจะดูวิดเจ็ตเหล่านี้ได้แม้ว่าแท็บเล็ตจะล็อกอยู่ก็ตาม วิดเจ็ตบางอย่างอาจไม่ได้มีไว้สำหรับหน้าจอล็อกของคุณ และอาจไม่ปลอดภัยที่จะเพิ่มที่นี่"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"รับทราบ"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"เริ่มเลย"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"ไม่มีการแจ้งเตือน"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"ไม่มีการแจ้งเตือนใหม่"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"การพักการแจ้งเตือนเปิดอยู่"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"ระบบจะลดระดับเสียงและจำนวนการแจ้งเตือนของอุปกรณ์โดยอัตโนมัติสูงสุด 2 นาทีเมื่อคุณได้รับการแจ้งเตือนพร้อมกันมากเกินไป"</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"ปิด"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ปลดล็อกเพื่อดูการแจ้งเตือนเก่า"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"อุปกรณ์นี้จัดการโดยผู้ปกครอง"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ต้องมีการตรวจสอบสิทธิ์ แตะเซ็นเซอร์ลายนิ้วมือเพื่อตรวจสอบสิทธิ์"</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"กำลังโทรอยู่"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"อินเทอร์เน็ตมือถือ"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"เชื่อมต่อแล้ว"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"เชื่อมต่อแล้วชั่วคราว"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"การเชื่อมต่อไม่ดี"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"เสร็จสิ้น"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"เก่งมาก"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ย้อนกลับ"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"หากต้องการย้อนกลับ ให้ใช้ 3 นิ้วปัดไปทางซ้ายหรือขวาที่ใดก็ได้บนทัชแพด"</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ทัชแพดแสดงภาพ 3 นิ้วเลื่อนไปทางขวาและซ้าย"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"หน้าจออุปกรณ์แสดงภาพเคลื่อนไหวของท่าทางสัมผัสย้อนกลับ"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ไฟแบ็กไลต์ของแป้นพิมพ์"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"ระบบควบคุมอุปกรณ์สมาร์ทโฮม"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"เข้าถึงระบบควบคุมอุปกรณ์สมาร์ทโฮมได้อย่างรวดเร็วผ่านภาพพักหน้าจอ"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"เลิกทำ"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"หากต้องการย้อนกลับ ให้ใช้ 3 นิ้วปัดไปทางซ้ายหรือขวาบนทัชแพด"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"หากต้องการไปที่หน้าแรก ให้ใช้ 3 นิ้วปัดขึ้นบนทัชแพด"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"หากต้องการดูแอปล่าสุด ให้ใช้ 3 นิ้วปัดขึ้นแล้วค้างไว้บนทัชแพด"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"หากต้องการดูแอปทั้งหมด ให้กดปุ่มดำเนินการบนแป้นพิมพ์"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"ใช้ทัชแพดเพื่อย้อนกลับ"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"ใช้ 3 นิ้วปัดไปทางซ้ายหรือขวา แตะเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับท่าทางสัมผัสต่างๆ"</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"ใช้ทัชแพดเพื่อไปยังหน้าแรก"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"ใช้ 3 นิ้วปัดขึ้น แตะเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับท่าทางสัมผัสต่างๆ"</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"ใช้ทัชแพดเพื่อดูแอปล่าสุด"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"ใช้ 3 นิ้วปัดขึ้นแล้วค้างไว้ แตะเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับท่าทางสัมผัสต่างๆ"</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"ใช้แป้นพิมพ์เพื่อดูแอปทั้งหมด"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"กดปุ่มดำเนินการได้ทุกเมื่อ แตะเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับท่าทางสัมผัสต่างๆ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/tiles_states_strings.xml b/packages/SystemUI/res/values-th/tiles_states_strings.xml
index 20f66da..8b7187b 100644
--- a/packages/SystemUI/res/values-th/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-th/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"ปิด"</item>
<item msgid="4875147066469902392">"เปิด"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"ไม่พร้อมใช้งาน"</item>
- <item msgid="2004750556637773692">"ปิด"</item>
- <item msgid="8968530753931637871">"เปิด"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"ไม่พร้อมใช้งาน"</item>
<item msgid="5044688398303285224">"ปิด"</item>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index a00bcc0..f836aca 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Performance"</string>
<string name="user_interface" msgid="3712869377953950887">"User Interface"</string>
<string name="thermal" msgid="6758074791325414831">"Thermal"</string>
+ <string name="custom" msgid="3337456985275158299">"Custom"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Mga Setting ng Custom na Trace"</string>
+ <string name="restore_default" msgid="5259420807486239755">"I-restore ang Default"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"One-hand mode"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Mga hearing device"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktibo"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Mga priyoridad na mode"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Tapos na"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Mga Setting"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Naka-on"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Naka-off"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Hindi ka maiistorbo ng mga tunog at pag-vibrate, maliban mula sa mga alarm, paalala, event, at tumatawag na tutukuyin mo. Maririnig mo pa rin ang kahit na anong piliin mong i-play kabilang ang mga musika, video, at laro."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Hindi ka maiistorbo ng mga tunog at pag-vibrate, maliban sa mga alarm. Maririnig mo pa rin ang anumang pipiliin mong i-play kabilang ang mga musika, video, at laro."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mabagal na nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string>
<string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Mga widget sa lock screen"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Mag-swipe pakaliwa para simulan ang communal na tutorial"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"I-customize"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"I-dismiss"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"ilagay ang napiling widget"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Mga widget ng lock screen"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Makikita ng sinuman ang mga widget sa lock screen, kahit naka-lock ang tablet."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"i-unselect ang widget"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Mga widget ng lock screen"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Para magbukas ng app gamit ang isang widget, kakailanganin mong i-verify na ikaw iyan. Bukod pa rito, tandaang puwedeng tingnan ng kahit na sino ang mga ito, kahit na naka-lock ang iyong tablet. Posibleng hindi para sa iyong lock screen ang ilang widget at posibleng hindi ligtas ang mga ito na idagdag dito."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Magsimula ngayon"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Walang mga notification"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Walang bagong notification"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Naka-on ang cooldown sa notification"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Babawasan ang volume at alerto nang hanggang 2 minuto kapag nakatanggap ng maraming notification."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"I-off"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"I-unlock para makita ang mga mas lumang notification"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Pinapamahalaan ng magulang mo itong device"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Kailangan ng pag-authenticate. Pindutin ang sensor para sa fingerprint para mag-authenticate."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Kasalukuyang may tawag sa telepono"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Nakakonekta"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Pansamantalang nakakonekta"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Mahina ang koneksyon"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Tapos na"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Magaling!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Bumalik"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Para bumalik, mag-swipe pakaliwa o pakanan gamit ang tatlong daliri kahit saan sa touchpad."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad na nagpapakita ng tatlong daliring gumagalaw pakanan at pakaliwa"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Screen ng device na nagpapakita ng animation para sa galaw sa pagbalik"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Backlight ng keyboard"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Mga Home Control"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Mabilis i-access ang home control bilang screensaver"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"I-undo"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Para bumalik, mag-swipe pakaliwa o pakanan gamit ang tatlong daliri sa touchpad."</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Para pumunta sa home, mag-swipe pataas gamit ang tatlong daliri sa touchpad"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Para tingnan ang kamakailang app, mag-swipe pataas at i-hold gamit ang tatlong daliri sa touchpad"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Para tingnan ang lahat ng iyong app, pindutin ang action key sa keyboard mo"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Gamitin ang iyong touchpad para bumalik"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Mag-swipe pakaliwa o pakanan gamit ang tatlong daliri. I-tap para matuto pa tungkol sa mga galaw."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Gamitin ang touchpad mo para pumunta sa home"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Mag-swipe pataas gamit ang tatlong daliri I-tap para matuto pa tungkol sa mga galaw."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Gamitin ang iyong touchpad para tingnan ang mga kamakailang app"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Mag-swipe pataas at i-hold gamit ang tatlong daliri. I-tap para matuto pa tungkol sa mga galaw."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Gamitin ang iyong keyboard para tingnan ang lahat ng app"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pindutin ang action key kahit kailan. I-tap para matuto pa tungkol sa mga galaw."</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/tiles_states_strings.xml b/packages/SystemUI/res/values-tl/tiles_states_strings.xml
index 85c4cfa..fe2827f 100644
--- a/packages/SystemUI/res/values-tl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-tl/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Naka-off"</item>
<item msgid="4875147066469902392">"Naka-on"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Hindi available"</item>
- <item msgid="2004750556637773692">"Naka-off"</item>
- <item msgid="8968530753931637871">"Naka-on"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Hindi available"</item>
<item msgid="5044688398303285224">"Naka-off"</item>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 855febe..b30df3d 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Performans"</string>
<string name="user_interface" msgid="3712869377953950887">"Kullanıcı Arayüzü"</string>
<string name="thermal" msgid="6758074791325414831">"Termal"</string>
+ <string name="custom" msgid="3337456985275158299">"Özel"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Özel İz Ayarları"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Varsayılanları Geri Yükle"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Tek el modu"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"İşitme cihazları"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Etkin"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Öncelik modları"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Bitti"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ayarlar"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Açık"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Kapalı"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Alarmlar, hatırlatıcılar, etkinlikler ve sizin seçtiğiniz kişilerden gelen çağrılar dışında hiçbir ses ve titreşimle rahatsız edilmeyeceksiniz. O sırada çaldığınız müzik, seyrettiğiniz video ya da oynadığınız oyunların sesini duymaya devam edeceksiniz."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Alarmlar dışında hiçbir ses ve titreşimle rahatsız edilmeyeceksiniz. O sırada çaldığınız müzik, seyrettiğiniz video ya da oynadığınız oyunların sesini duymaya devam edeceksiniz."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Yavaş şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string>
<string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Kilit ekranındaki widget\'lar"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Ortak eğitimi başlatmak için sola kaydırın"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Özelleştir"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Kapat"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"seçilen widget\'ı yerleştir"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Kilit ekranı widget\'ları"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Kilit ekranınızdaki widget\'lar, tabletiniz kilitliyken bile herkes tarafından görüntülenebilir."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"widget\'ın seçimini kaldırın"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Kilit ekranı widget\'ları"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Widget kullanarak bir uygulamayı açmak için kimliğinizi doğrulamanız gerekir. Ayrıca, tabletiniz kilitliyken bile widget\'ların herkes tarafından görüntülenebileceğini unutmayın. Bazı widget\'lar kilit ekranınız için tasarlanmamış olabileceğinden buraya eklenmeleri güvenli olmayabilir."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Anladım"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Şimdi başlat"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Bildirim yok"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Yeni bildirim yok"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Bildirim şiddetini düşürme etkin"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Aynı anda çok sayıda bildirim aldığınızda 2 dakika boyunca otomatik olarak cihazınızın sesi kısılır ve uyarıları azaltılır."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Kapat"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Eski bildirimler için kilidi açın"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Bu cihaz ebeveyniniz tarafından yönetiliyor"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Kimlik doğrulaması gerekiyor. Kimlik doğrulaması için parmak izi sensörüne dokunun."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Devam eden telefon görüşmesi"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobil veri"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Bağlı"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Geçici olarak bağlandı"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Bağlantı zayıf"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Bitti"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Tebrikler!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Geri dön"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Geri dönmek için dokunmatik alanın herhangi bir yerinde üç parmağınızla sola veya sağa kaydırın."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Sağa ve sola hareket eden üç parmağın gösterildiği dokunmatik alan"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Geri hareketi animasyonunu gösteren cihaz ekranı"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klavye aydınlatması"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Ev Kontrolleri"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Ekran koruyucu olarak ev kontrollerinize hızla erişin"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Geri al"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Geri dönmek için dokunmatik alanda üç parmağınızla sola veya sağa kaydırın"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Ana sayfaya gitmek için dokunmatik alanda üç parmağınızla yukarı kaydırın"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Son uygulamaları görüntülemek için dokunmatik alanda üç parmağınızla yukarı kaydırıp basılı tutun"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Tüm uygulamalarınızı görüntülemek için klavyenizdeki eylem tuşuna basın"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Geri dönmek için dokunmatik alanınızı kullanın"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Üç parmağınızla sola veya sağa kaydırın. Daha fazla hareket öğrenmek için dokunun."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Ana sayfaya gitmek için dokunmatik alanınızı kullanın"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Üç parmağınızla yukarı kaydırın. Daha fazla hareket öğrenmek için dokunun."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Son uygulamaları görüntülemek için dokunmatik alanınızı kullanın"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Üç parmağınızla yukarı kaydırıp basılı tutun. Daha fazla hareket öğrenmek için dokunun."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Tüm uygulamaları görüntülemek için klavyenizi kullanın"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"İstediğiniz zaman eylem tuşuna basın. Daha fazla hareket öğrenmek için dokunun."</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/tiles_states_strings.xml b/packages/SystemUI/res/values-tr/tiles_states_strings.xml
index 1c9224b..1ed106f 100644
--- a/packages/SystemUI/res/values-tr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-tr/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Kapalı"</item>
<item msgid="4875147066469902392">"Açık"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Yok"</item>
- <item msgid="2004750556637773692">"Kapalı"</item>
- <item msgid="8968530753931637871">"Açık"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Kullanılamıyor"</item>
<item msgid="5044688398303285224">"Kapalı"</item>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index dec917b..7e72f7e 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Продуктивність"</string>
<string name="user_interface" msgid="3712869377953950887">"Інтерфейс користувача"</string>
<string name="thermal" msgid="6758074791325414831">"Нагрівання"</string>
+ <string name="custom" msgid="3337456985275158299">"Власні"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Власні налаштування трасування"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Відновити налаштування за умовчанням"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Режим керування однією рукою"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слухові апарати"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Під’єднано"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Режими пріоритету"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Готово"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Налаштування"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Увімкнено"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Вимкнено"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Ви отримуватиме звукові та вібросигнали лише для вибраних будильників, нагадувань, подій і абонентів. Однак ви чутимете все, що захочете відтворити, зокрема музику, відео й ігри."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Ви отримуватиме звукові та вібросигнали лише для будильників. Однак ви чутимете все, що захочете відтворити, зокрема музику, відео й ігри."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Повільне заряджання • <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> • Заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Віджети на заблокованому екрані"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Проведіть пальцем уліво, щоб відкрити спільний навчальний посібник"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Налаштувати"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Закрити"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"розмістити вибраний віджет"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Віджети для заблокованого екрана"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Будь-хто бачитиме віджети навіть на заблокованому екрані планшета."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"скасувати вибір віджета"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Віджети для заблокованого екрана"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Щоб відкрити додаток за допомогою віджета, вам потрібно буде підтвердити особу. Пам’ятайте також, що бачити віджети можуть усі, навіть коли планшет заблоковано. Можливо, деякі віджети не призначені для заблокованого екрана, і додавати їх на нього може бути небезпечно."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Почати зараз"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Сповіщень немає"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Немає нових сповіщень"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Зниження гучності сповіщень увімкнено"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Коли ви отримуєте забагато сповіщень за раз, пристрій автоматично знижує їх гучність і кількість на період до 2 хвилин."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Вимкнути"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Розблокуйте, щоб переглянути старіші"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Цим пристроєм керує батько або мати"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Пройдіть автентифікацію. Для цього торкніться сканера відбитків пальців."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Активний телефонний виклик"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобільний трафік"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Підключено"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Тимчасово з’єднано"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Погане з’єднання"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Чудово!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Щоб перейти назад, проведіть трьома пальцями вліво або вправо по сенсорній панелі."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Сенсорна панель із зображенням трьох пальців, що рухаються вправо й уліво"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Екран пристрою, на якому показано анімацію щодо жесту \"Назад\""</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Підсвічування клавіатури"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Автоматизація дому"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Швидкий доступ до керування домом через заставку"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Відмінити"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Щоб перейти назад, проведіть трьома пальцями вліво або вправо по сенсорній панелі"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Щоб перейти на головний екран, проведіть трьома пальцями вгору по сенсорній панелі"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Щоб переглянути останні додатки, проведіть трьома пальцями вгору по сенсорній панелі й утримуйте їх"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Щоб переглянути всі додатки, натисніть клавішу дії на клавіатурі"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Щоб повернутися, використовуйте сенсорну панель"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Проведіть трьома пальцями вліво чи вправо. Натисніть, щоб дізнатися про інші жести."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Щоб перейти на головний екран, використовуйте сенсорну панель"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Проведіть трьома пальцями вгору. Натисніть, щоб дізнатися про інші жести."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Щоб переглянути останні додатки, використовуйте сенсорну панель"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Проведіть трьома пальцями вгору й утримуйте їх на екрані. Натисніть, щоб дізнатися про інші жести."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Щоб переглянути всі додатки, використовуйте клавіатуру"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Будь-коли натисніть клавішу дії. Натисніть, щоб дізнатися про інші жести."</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/tiles_states_strings.xml b/packages/SystemUI/res/values-uk/tiles_states_strings.xml
index 9e31283..61e62e4 100644
--- a/packages/SystemUI/res/values-uk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-uk/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Вимкнено"</item>
<item msgid="4875147066469902392">"Увімкнено"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Недоступно"</item>
- <item msgid="2004750556637773692">"Вимкнено"</item>
- <item msgid="8968530753931637871">"Увімкнено"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Недоступно"</item>
<item msgid="5044688398303285224">"Вимкнено"</item>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 0530655..94586b7 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"کارکردگی"</string>
<string name="user_interface" msgid="3712869377953950887">"یوزر انٹرفیس"</string>
<string name="thermal" msgid="6758074791325414831">"تھرمل"</string>
+ <string name="custom" msgid="3337456985275158299">"حسب ضرورت"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"حسب ضرورت ٹریس کی ترتیبات"</string>
+ <string name="restore_default" msgid="5259420807486239755">"ڈیفالٹ بحال کریں"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ایک ہاتھ کی وضع"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"سماعت کے آلات"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"فعال"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"ترجیحی وضع"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"ہو گیا"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ترتیبات"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"آن ہے"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"آف ہے"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"الارمز، یاددہانیوں، ایونٹس اور آپ کے متعین کردہ کالرز کے علاوہ، آپ آوازوں اور وائبریشنز سے ڈسٹرب نہیں ہوں گے۔ موسیقی، ویڈیوز اور گیمز سمیت آپ ابھی بھی ہر وہ چیز سنیں گے جسے چلانے کا آپ انتخاب کرتے ہیں۔"</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"الارمز کے علاوہ، آپ آوازوں اور وائبریشنز سے ڈسٹرب نہیں ہوں گے۔ موسیقی، ویڈیوز اور گیمز سمیت آپ ہر وہ چیز سنیں گے جسے چلانے کا آپ انتخاب کرتے ہیں۔"</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • آہستہ چارج ہو رہا ہے • <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> • چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"مقفل اسکرین پر ویجیٹس"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"کمیونل ٹیوٹوریل شروع کرنے کے لیے بائیں سوائپ کریں"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"حسب ضرورت بنائیں"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"برخاست کریں"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"منتخب ویجیٹ رکھیں"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"مقفل اسکرین کے ویجیٹس"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"کوئی بھی آپ کی مقفل اسکرین پر ویجیٹ دیکھ سکتا ہے اگرچہ آپ کا ٹیبلیٹ مقفل ہو۔"</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ویجیٹ غیر منتخب کریں"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"مقفل اسکرین کے ویجیٹس"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ویجیٹ کے ذریعے ایپ کھولنے کے لیے آپ کو تصدیق کرنی ہوگی کہ یہ آپ ہی ہیں۔ نیز، ذہن میں رکھیں کہ کوئی بھی انہیں دیکھ سکتا ہے، یہاں تک کہ جب آپ کا ٹیبلیٹ مقفل ہو۔ ہو سکتا ہے کچھ ویجٹس آپ کی لاک اسکرین کے لیے نہ بنائے گئے ہوں اور یہاں شامل کرنا غیر محفوظ ہو سکتا ہے۔"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"سمجھ آ گئی"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"ابھی شروع کریں"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"کوئی اطلاعات نہیں ہیں"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"کوئی نئی اطلاعات نہیں"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"ںوٹیفیکیشن کول ڈاؤن آن ہے"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"جب آپ کو ایک ساتھ بہت زیادہ اطلاعات موصول ہوتی ہیں تو آپ کے آلے کا والیوم اور الرٹس خودکار طور پر 2 منٹ تک کم ہو جاتے ہیں۔"</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"آف کریں"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"پرانی اطلاعات دیکھنے کیلئے غیر مقفل کریں"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"یہ آلہ آپ کے والدین کے زیر انتظام ہے"</string>
@@ -1230,7 +1236,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"توثیق مطلوب ہے۔ توثیق کرنے کے لیے فنگر پرنٹ سینسر کو ٹچ کریں۔"</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"جاری فون کال"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"موبائل ڈیٹا"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="NETWORKMODE">%2$s</xliff:g> / <xliff:g id="STATE">%1$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"منسلک ہے"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"عارضی طور پر منسلک ہے"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"کمزور کنکشن"</string>
@@ -1384,7 +1389,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ہو گیا"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"بہترین!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"واپس جائیں"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"واپس جانے کے لیے، ٹچ پیڈ پر کہیں بھی تین انگلیوں کی مدد سے دائیں یا بائیں سوائپ کریں۔"</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ٹچ پیڈ دائیں اور بائیں حرکت کرتی ہوئی تین انگلیاں دکھا رہا ہے"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"آلہ کی اسکرین پیچھے جانے کے اشارے کے لیے اینیمیشن دکھا رہی ہے"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"کی بورڈ بیک لائٹ"</string>
@@ -1392,28 +1400,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"ہوم کنٹرولز"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"اسکرین سیور کے بطور اپنے ہوم کنٹرولز تک فوری رسائی حاصل کریں"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"کالعدم کریں"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"واپس جانے کے لیے، ٹچ پیڈ پر تین انگلیوں کی مدد سے بائیں یا دائیں سوائپ کریں"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"ہوم پر جانے کے لیے، ٹچ پیڈ پر تین انگلیوں کی مدد سے اوپر سوائپ کریں"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"حالیہ ایپس دیکھنے کے لیے، ٹچ پیڈ پر تین انگلیوں سے اوپر سوائپ کریں اور دبائے رکھیں"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"اپنی سبھی ایپس دیکھنے کے لیے، اپنے کی بورڈ پر ایکشن کلید دبائیں"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"واپس جانے کے لیے اپنے ٹچ پیڈ کا استعمال کریں"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"تین انگلیوں سے دائیں یا بائیں طرف سوائپ کریں۔ مزید اشارے جاننے کے لیے تھپتھپائیں۔"</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"ہوم پر جانے کے لیے اپنے ٹچ پیڈ کا استعمال کریں"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"تین انگلیوں سے اوپر سوائپ کریں۔ مزید اشارے جاننے کے لیے تھپتھپائیں۔"</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"حالیہ ایپس دیکھنے کے لیے اپنے ٹچ پیڈ کا استعمال کریں"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"تین انگلیوں سے اوپر کی طرف سوائپ کریں اور دبائے رکھیں۔ مزید اشارے جاننے کے لیے تھپتھپائیں۔"</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"سبھی ایپس دیکھنے کے لیے اپنے کی بورڈ کا استعمال کریں"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"کسی بھی وقت ایکشن کلید دبائیں۔ مزید اشارے جاننے کے لیے تھپتھپائیں۔"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ur/tiles_states_strings.xml b/packages/SystemUI/res/values-ur/tiles_states_strings.xml
index e398b2f..ebbc30e 100644
--- a/packages/SystemUI/res/values-ur/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ur/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"آف ہے"</item>
<item msgid="4875147066469902392">"آن ہے"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"دستیاب نہیں ہے"</item>
- <item msgid="2004750556637773692">"آف ہے"</item>
- <item msgid="8968530753931637871">"آن ہے"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"دستیاب نہیں ہے"</item>
<item msgid="5044688398303285224">"آف ہے"</item>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 11c0dff..3f60776 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Unumdorlik"</string>
<string name="user_interface" msgid="3712869377953950887">"Foydalanuvchi interfeysi"</string>
<string name="thermal" msgid="6758074791325414831">"Termal"</string>
+ <string name="custom" msgid="3337456985275158299">"Maxsus"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Maxsus trassirovka sozlamalari"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Asliga qaytarish"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Ixcham rejim"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Eshitish qurilmalari"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Faol"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Muhim rejimlar"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Tayyor"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Sozlamalar"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Yoniq"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Yoqilmagan"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Turli ovoz va tebranishlar endi sizni bezovta qilmaydi. Biroq, signallar, eslatmalar, tadbirlar haqidagi bildirishnomalar va siz tanlagan abonentlardan kelgan chaqiruvlar bundan mustasno. Lekin, ijro etiladigan barcha narsalar, jumladan, musiqa, video va o‘yinlar ovozi eshitiladi."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Turli ovoz va tebranishlar endi sizni bezovta qilmaydi. Biroq, signallar bundan mustasno. Lekin, ijro etiladigan barcha narsalar, jumladan, musiqa, video va o‘yinlar ovozi eshitiladi."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sekin quvvat olmoqda • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi"</string>
<string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Quvvat olmoqda • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Ekran qulfidagi vidjetlar"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Qoʻllanma bilan tanishish uchun chapga suring"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Moslash"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Yopish"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"tanlangan vidjetni joylash"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Ekran qulfi vidjetlari"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Ekran quflidagi vidjetlar hammaga koʻrinadi, hatto planshet qulflanganda ham."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"vidjetni bekor qilish"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Ekran qulfi vidjetlari"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Ilovani vidjet orqali ochish uchun shaxsingizni tasdiqlashingiz kerak. Shuningdek, planshet qulflanganda ham bu axborotlar hammaga koʻrinishini unutmang. Ayrim vidjetlar ekran qulfiga moslanmagan va ularni bu yerda chiqarish xavfli boʻlishi mumkin."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Boshlash"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Bildirishnomalar yo‘q"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Yangi bildirishoma yoʻq"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Bildirishnomalarni sekinlatish yoniq"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Bir vaqtda juda koʻp bildirishnoma olsangiz, qurilmangiz tovushi va ogohlantirishlar 2 daqiqagacha avtomatik pasaytiriladi."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Faolsizlantirish"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Eskilarini koʻrish uchun qulfni yeching"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Bu qurilmani ota-onangiz boshqaradi"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Haqiqiylikni tekshirish talab etiladi. Autentifikatsiya uchun barmoq izi skaneriga tegining."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Joriy telefon chaqiruvi"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobil internet"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Ulangan"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Vaqtincha ulangan"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Aloqa beqaror"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Tayyor"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Barakalla!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Orqaga qaytish"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Ortga qaytish uchun sensorli panelda uchta barmoqni chapga yoki oʻngga suring."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Sensorli panelda uchta barmoq chapga va oʻngga harakatlanishi"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Qurilma ekranidagi ortga qaytish ishorasi animatsiyasi"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klaviatura orqa yoritkichi"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Uy boshqaruvi"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Uy boshqaruvi tugmalarini ekran lavhasida tezkor oching"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Bekor qilish"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Orqaga qaytish uchun sensorli panelda uchta barmoq bilan chapga yoki oʻngga suring"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Bosh ekranga qaytish uchun sensorli panelda uchta barmoq bilan chapga yoki oʻngga suring"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Oxirgi ilovalarni koʻrish uchun sensorli panelda uchta barmoq bilan tepaga surib, bosib turing"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Barcha ishoralarni koʻrish uchun klaviaturadagi amal tugmasini bosing"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Sensorli panel orqali orqaga qaytish"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Uchta barmoq bilan chapga yoki oʻngga suring. Boshqa ishoralar bilan tanishish uchun bosing."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Sensorli panel orqali bosh ekranga qaytish"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Uchta barmoq bilan tepaga suring. Boshqa ishoralar bilan tanishish uchun bosing."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Sensorli panel orqali oxirgi ilovalarni koʻrish"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Uchta barmoq bilan tepaga surib, bosib turing. Boshqa ishoralar bilan tanishish uchun bosing."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Klaviatura orqali barcha ilovalarni koʻrish"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Amal tugmasini istalganda bosing. Boshqa ishoralar bilan tanishish uchun bosing."</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz/tiles_states_strings.xml b/packages/SystemUI/res/values-uz/tiles_states_strings.xml
index 49b774f..2ae81123 100644
--- a/packages/SystemUI/res/values-uz/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-uz/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Oʻchiq"</item>
<item msgid="4875147066469902392">"Yoniq"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Mavjud emas"</item>
- <item msgid="2004750556637773692">"Oʻchiq"</item>
- <item msgid="8968530753931637871">"Yoniq"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Ishlamaydi"</item>
<item msgid="5044688398303285224">"Oʻchiq"</item>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 5bc1e03..dcf8051 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Hiệu suất"</string>
<string name="user_interface" msgid="3712869377953950887">"Giao diện người dùng"</string>
<string name="thermal" msgid="6758074791325414831">"Nhiệt"</string>
+ <string name="custom" msgid="3337456985275158299">"Tuỳ chỉnh"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Cài đặt dấu vết tuỳ chỉnh"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Khôi phục giá trị mặc định"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Chế độ một tay"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Thiết bị trợ thính"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Đang hoạt động"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Chế độ ưu tiên"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Xong"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Cài đặt"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Đang bật"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Đang tắt"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Bạn sẽ không bị làm phiền bởi âm thanh và tiếng rung, ngoại trừ báo thức, lời nhắc, sự kiện và người gọi mà bạn chỉ định. Bạn sẽ vẫn nghe thấy mọi thứ bạn chọn phát, bao gồm nhạc, video và trò chơi."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Bạn sẽ không bị làm phiền bởi âm thanh và tiếng rung, ngoại trừ báo thức. Bạn sẽ vẫn nghe thấy mọi thứ bạn chọn phát, bao gồm nhạc, video và trò chơi."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc chậm • Sẽ đầy sau <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> • Đang sạc • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Các tiện ích trên màn hình khoá"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Vuốt sang trái để bắt đầu xem hướng dẫn chung"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Tuỳ chỉnh"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Đóng"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"đặt tiện ích đã chọn vào vị trí"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Tiện ích trên màn hình khoá"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Ai cũng thấy được các tiện ích trên màn hình khoá, dù bạn đã khoá máy tính bảng."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"bỏ chọn tiện ích"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Tiện ích trên màn hình khoá"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Để dùng tiện ích mở một ứng dụng, bạn cần xác minh danh tính của mình. Ngoài ra, hãy lưu ý rằng bất kỳ ai cũng có thể xem các tiện ích này, ngay cả khi máy tính bảng của bạn được khoá. Một số tiện ích có thể không dành cho màn hình khoá và không an toàn khi thêm vào đây."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Tôi hiểu"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Bắt đầu ngay"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Không có thông báo nào"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Không có thông báo mới"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Chế độ Giảm dần âm lượng thông báo đang bật"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Khi bạn nhận quá nhiều thông báo cùng lúc, âm lượng và cảnh báo tự động giảm trong tối đa 2 phút."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Tắt"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Mở khoá để xem thông báo cũ"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Thiết bị này do cha mẹ của bạn quản lý"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Bạn cần phải xác thực. Hãy chạm vào cảm biến vân tay để xác thực."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Đang gọi điện thoại"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Dữ liệu di động"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Đã kết nối"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tạm thời có kết nối"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Kết nối kém"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Xong"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Tuyệt vời!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Quay lại"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Để quay lại, hãy vuốt sang trái hoặc sang phải bằng 3 ngón tay ở vị trí bất kỳ trên bàn di chuột."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Minh hoạ thao tác di chuyển sang phải và sang trái bằng 3 ngón tay trên bàn di chuột"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Màn hình thiết bị hiện ảnh động minh hoạ cử chỉ quay lại"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Đèn nền bàn phím"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Điều khiển nhà"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Điều khiển nhà nhanh bằng trình bảo vệ màn hình"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Huỷ"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Để quay lại, hãy dùng 3 ngón tay vuốt sang trái hoặc phải trên bàn di chuột"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Để trở về màn hình chính, hãy dùng 3 ngón tay vuốt lên trên bàn di chuột"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Để xem các ứng dụng gần đây, hãy dùng 3 ngón tay vuốt lên và giữ trên bàn di chuột"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Để xem tất cả ứng dụng của bạn, hãy nhấn phím hành động trên bàn phím"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Dùng bàn di chuột để quay lại"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Dùng 3 ngón tay vuốt sang trái hoặc sang phải. Hãy nhấn để tìm hiểu các cử chỉ khác."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Dùng bàn di chuột để chuyển đến màn hình chính"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Dùng 3 ngón tay vuốt lên. Hãy nhấn để tìm hiểu các cử chỉ khác."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Dùng bàn di chuột để xem các ứng dụng gần đây"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Dùng 3 ngón tay vuốt lên và giữ. Hãy nhấn để tìm hiểu các cử chỉ khác."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Sử dụng bàn phím để xem tất cả ứng dụng"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Nhấn phím hành động bất cứ lúc nào. Hãy nhấn để tìm hiểu các cử chỉ khác."</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/tiles_states_strings.xml b/packages/SystemUI/res/values-vi/tiles_states_strings.xml
index e683518..d9d8af1 100644
--- a/packages/SystemUI/res/values-vi/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-vi/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Đang tắt"</item>
<item msgid="4875147066469902392">"Đang bật"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Không có"</item>
- <item msgid="2004750556637773692">"Đang tắt"</item>
- <item msgid="8968530753931637871">"Đang bật"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Không hoạt động"</item>
<item msgid="5044688398303285224">"Đang tắt"</item>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 1a58804..6162da8 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"性能"</string>
<string name="user_interface" msgid="3712869377953950887">"界面"</string>
<string name="thermal" msgid="6758074791325414831">"散热"</string>
+ <string name="custom" msgid="3337456985275158299">"自定义"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"自定义跟踪记录设置"</string>
+ <string name="restore_default" msgid="5259420807486239755">"恢复默认设置"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"单手模式"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"助听装置"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"已连接"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"优先模式"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"完成"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"设置"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"已开启"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"已关闭"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"您将不会受到声音和振动的打扰(闹钟、提醒、活动和所指定来电者的相关提示音除外)。您依然可以听到您选择播放的任何内容(包括音乐、视频和游戏)的相关音效。"</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"您将不会受到声音和振动的打扰(闹钟提示音除外)。您依然可以听到您选择播放的任何内容(包括音乐、视频和游戏)的相关音效。"</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在慢速充电 • 将于 <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> • 正在充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"锁定屏幕上的微件"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"向左滑动即可启动公共教程"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"自定义"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"关闭"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"放置所选微件"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"锁屏微件"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"任何人都可以查看锁屏上的微件,即使平板电脑已锁定。"</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"取消选中微件"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"锁定的屏幕中的微件"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"若要使用微件打开应用,您需要验证是您本人在操作。另外请注意,任何人都可以查看此类微件,即使您的平板电脑已锁定。有些微件可能不适合显示在锁定的屏幕中,因此添加到这里可能不安全。"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"知道了"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"立即开始"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"没有通知"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"没有新通知"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"“通知音量渐降”设置已开启"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"当您一次收到过多通知时,设备音量会自动降低,提醒次数也会自动减少,这种状况最长可持续 2 分钟。"</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"关闭"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"解锁即可查看旧通知"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"此设备由您的家长管理"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"需要进行身份验证。请轻触指纹传感器以验证身份。"</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"正在进行通话"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"移动数据网络"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"已连接"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"已暂时连接"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"连接状况不佳"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"完成"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"太棒了!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"返回"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"如要返回,请使用三根手指在触控板上的任意位置左滑或右滑。"</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"触控板,其中显示了三根手指右移和左移"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"设备屏幕,其中显示了返回手势的动画"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"键盘背光"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"家居控制"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"通过屏保快速访问家居控制功能"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"撤消"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"如要返回,请用三根手指在触控板上向左或向右滑动"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"如要前往主屏幕,请用三根手指在触控板上向上滑动"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"如要查看最近用过的应用,请用三根手指在触控板上向上滑动并按住"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"如要查看所有应用,请按下键盘上的快捷操作按键"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"使用触控板返回"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"用三根手指向左或向右滑动。点按即可了解更多手势。"</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"使用触控板前往主屏幕"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"用三根手指向上滑动。点按即可了解更多手势。"</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"使用触控板查看最近用过的应用"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"用三根手指向上滑动并按住。点按即可了解更多手势。"</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"使用键盘查看所有应用"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"您可随时按下快捷操作按键。点按即可了解更多手势。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml
index e16e42a..0446a1b 100644
--- a/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"已关闭"</item>
<item msgid="4875147066469902392">"已开启"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"不可用"</item>
- <item msgid="2004750556637773692">"已关闭"</item>
- <item msgid="8968530753931637871">"已开启"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"不可用"</item>
<item msgid="5044688398303285224">"已关闭"</item>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 7954e35..9c1049b 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"效能"</string>
<string name="user_interface" msgid="3712869377953950887">"使用者介面"</string>
<string name="thermal" msgid="6758074791325414831">"熱能"</string>
+ <string name="custom" msgid="3337456985275158299">"自訂"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"自訂 Trace 設定"</string>
+ <string name="restore_default" msgid="5259420807486239755">"還原預設值"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"單手模式"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"助聽器"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"已連線"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"優先模式"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"完成"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"設定"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"開啟"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"關閉"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"你不會受到聲音和震動騷擾 (鬧鐘、提醒、活動和你指定的來電者鈴聲除外)。當你選擇播放音樂、影片和遊戲等,仍可以聽到該內容的聲音。"</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"你不會受到聲音和震動騷擾 (鬧鐘除外)。當你選擇播放音樂、影片和遊戲等,仍可以聽到該內容的聲音。"</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 慢速充電中 • <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> • 充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"上鎖畫面上的小工具"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"向左滑動即可開始共用教學課程"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"自訂"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"關閉"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"放置所選小工具"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"上鎖畫面小工具"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"任何人都可查看上鎖畫面的小工具,即使平板電腦已上鎖亦然。"</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"取消揀小工具"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"上鎖畫面小工具"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"如要使用小工具開啟應用程式,系統會要求你驗證身分。請注意,即使平板電腦已鎖定,所有人還是能查看小工具。部分小工具可能不適用於上鎖畫面,而且新增至這裡後可能會有安全疑慮。"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"知道了"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"立即開始"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"沒有通知"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"沒有新通知"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"調低通知強度功能已開啟"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"如果同一時間收到太多通知,裝置會在最長 2 分鐘內調低音量,並減少警示。"</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"關閉"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"解鎖即可查看舊通知"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"此裝置由你的家長管理"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"需要驗證。掂一下指紋感應器就可以驗證。"</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"通話中"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"流動數據"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"已連線"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"已暫時連線"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"連線速度欠佳"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"完成"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"太好了!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"返回"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"用三隻手指在觸控板上任何一處左右滑動即可返回。"</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"觸控板上有三隻手指左右移動"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"裝置畫面顯示返回手勢動畫"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"鍵盤背光"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"智能家居"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"在螢幕保護程式畫面上控制智能家居"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"復原"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"如要返回,請用三隻手指在觸控板上向左或向右滑動"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"如要返回主畫面,請用三隻手指在觸控板上向上滑動"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"如要查看最近使用的應用程式,請用三隻手指在觸控板上向上滑動並按住"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"如要查看所有應用程式,請在鍵盤上按下快捷操作鍵"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"使用觸控板返回"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"用三隻手指向左或向右滑動。輕按即可瞭解更多手勢。"</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"使用觸控板返回主畫面"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"用三隻手指向上滑動。輕按即可瞭解更多手勢。"</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"使用觸控板查看最近使用的應用程式"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"用三隻手指向上滑動並按住。輕按即可瞭解更多手勢。"</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"使用鍵盤查看所有應用程式"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"隨時按下快捷操作鍵。輕按即可瞭解更多手勢。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml
index 57b4d20..cca7ac4 100644
--- a/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"已關閉"</item>
<item msgid="4875147066469902392">"已開啟"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"無法使用"</item>
- <item msgid="2004750556637773692">"關閉"</item>
- <item msgid="8968530753931637871">"開啟"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"無法使用"</item>
<item msgid="5044688398303285224">"已關閉"</item>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index b7043b5..1ac8ec4 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"效能"</string>
<string name="user_interface" msgid="3712869377953950887">"使用者介面"</string>
<string name="thermal" msgid="6758074791325414831">"熱成像"</string>
+ <string name="custom" msgid="3337456985275158299">"自訂"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"自訂追蹤記錄設定"</string>
+ <string name="restore_default" msgid="5259420807486239755">"還原為預設值"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"單手模式"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"助聽器"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"已連線"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"優先模式"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"完成"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"設定"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"開啟"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"關閉"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"裝置不會發出音效或震動造成干擾,但是會保留與鬧鐘、提醒、活動和指定來電者有關的設定。如果你選擇播放音樂、影片和遊戲等內容,還是可以聽見相關音訊。"</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"裝置不會發出音效或震動造成干擾,但是會保留鬧鐘響鈴。如果你選擇播放音樂、影片和遊戲等內容,還是可以聽見相關音訊。"</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 慢速充電中 • 將於 <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> • 充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"螢幕鎖定畫面上的小工具"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"向左滑動即可啟動通用教學課程"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"自訂"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"關閉"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"放置所選小工具"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"螢幕鎖定畫面小工具"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"即使平板電腦已鎖定,所有人仍可查看螢幕鎖定畫面上的小工具。"</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"取消選取小工具"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"螢幕鎖定小工具"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"如要使用小工具開啟應用程式,系統會要求你驗證身分。請注意,即使平板電腦已鎖定,所有人還是能查看小工具。某些小工具可能不適用於螢幕鎖定畫面,而且新增到這裡可能有安全疑慮。"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"我知道了"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"立即開始"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"沒有通知"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"沒有新通知"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"通知緩和設定已開啟"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"如果一次收到過多通知,裝置就會自動降低音量並減少通知數量,持續時間最多 2 分鐘。"</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"關閉"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"解鎖即可查看舊通知"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"這個裝置是由你的家長管理"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"需要驗證。輕觸指紋感應器即可進行驗證。"</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"通話中"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"行動數據"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"已連線"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"已暫時建立連線"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"連線品質不佳"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"完成"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"太棒了!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"返回"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"如要返回,請用三指在觸控板上向左或右滑動。"</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"動畫顯示三指正在觸控板上向左右移動"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"裝置畫面顯示返回手勢的動畫"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"鍵盤背光"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"居家控制"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"在螢幕保護程式畫面上快速存取居家控制功能"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"復原"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"如要返回,請在觸控板上用三指向左或向右滑動"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"如要前往主畫面,請在觸控板上用三指向上滑動"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"如要查看最近使用的應用程式,請在觸控板上向上滑動並按住"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"如要查看所有應用程式,請按下鍵盤上的快捷操作鍵"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"使用觸控板返回"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"用三指向左或向右滑動。輕觸即可進一步瞭解手勢。"</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"使用觸控板前往主畫面"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"用三指向上滑動。輕觸即可進一步瞭解手勢。"</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"使用觸控板查看最近使用的應用程式"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"用三指向上滑動並按住。輕觸即可進一步瞭解手勢。"</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"使用鍵盤查看所有應用程式"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"你隨時可以按下快捷操作鍵。輕觸即可進一步瞭解手勢。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml
index 3a64fdd..4cc5804 100644
--- a/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"已關閉"</item>
<item msgid="4875147066469902392">"已開啟"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"無法使用"</item>
- <item msgid="2004750556637773692">"已關閉"</item>
- <item msgid="8968530753931637871">"已開啟"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"無法使用"</item>
<item msgid="5044688398303285224">"已關閉"</item>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 436c7c6..3a34c47 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -388,6 +388,9 @@
<string name="performance" msgid="6552785217174378320">"Ukusebenza"</string>
<string name="user_interface" msgid="3712869377953950887">"Okusetshenziswa Kubonwa"</string>
<string name="thermal" msgid="6758074791325414831">"Ithermal"</string>
+ <string name="custom" msgid="3337456985275158299">"Okumuntu ngamunye"</string>
+ <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Amasethingi Okulandelela Okomuntu Ngamunye"</string>
+ <string name="restore_default" msgid="5259420807486239755">"Buyisela Okuzenzakalelayo"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Imodi yesandla esisodwa"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Izinsizakuzwa"</string>
<string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Kuyasebenza"</string>
@@ -429,9 +432,13 @@
<string name="zen_modes_dialog_title" msgid="4159138230418567383">"Amamodi okubalulekile"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Kwenziwe"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Amasethingi"</string>
- <!-- no translation found for zen_mode_on (9085304934016242591) -->
+ <string name="zen_mode_on" msgid="9085304934016242591">"Vuliwe"</string>
+ <string name="zen_mode_off" msgid="1736604456618147306">"Valiwe"</string>
+ <!-- no translation found for zen_mode_set_up (7457957033034460064) -->
<skip />
- <!-- no translation found for zen_mode_off (1736604456618147306) -->
+ <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) -->
+ <skip />
+ <!-- no translation found for zen_mode_active_modes (1625850411578488856) -->
<skip />
<string name="zen_priority_introduction" msgid="3159291973383796646">"Ngeke uphazanyiswe imisindo nokudlidliza, ngaphandle kusukela kuma-alamu, izikhumbuzi, imicimbi, nabafonayo obacacisayo. Usazozwa noma yini okhetha ukuyidlala okufaka umculo, amavidiyo, namageyimu."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Ngeke uze uphazanyiswe imisindo nokudlidliza, ngaphandle kusukela kuma-alamu. Usazozwa noma yini okhetha ukuyidlala okufaka umculo, amavidiyo, namageyimu."</string>
@@ -471,6 +478,8 @@
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ishaja kancane • Izogcwala ngo-<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> • Iyashaja • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Amawijethi ekukhiyeni isikrini"</string>
+ <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) -->
+ <skip />
<string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swayiphela kwesokunxele ukuze uqale okokufundisa komphakathi"</string>
<string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Enza ngendlela oyifisayo"</string>
<string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Chitha"</string>
@@ -499,8 +508,7 @@
<string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"beka iwijethi ekhethiwe"</string>
<string name="communal_widget_picker_title" msgid="1953369090475731663">"Amawijethi wesikrini esikhiyiwe"</string>
<string name="communal_widget_picker_description" msgid="490515450110487871">"Noma ubani angabuka amawijethi ngisho noma ithebulethi ikhiyiwe."</string>
- <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) -->
- <skip />
+ <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"yeka ukukhetha iwijethi"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Amawijethi wesikrini esikhiyiwe"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Ukuze uvule i-app usebenzisa iwijethi, uzodinga ukuqinisekisa ukuthi nguwe. Futhi, khumbula ukuthi noma ubani angakwazi ukuzibuka, nanoma ithebhulethi yakho ikhiyiwe. Amanye amawijethi kungenzeka abengahloselwe ukukhiya isikrini sakho futhi kungenzeka awaphephile ukuthi angafakwa lapha."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Ngiyezwa"</string>
@@ -557,10 +565,8 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Qala manje"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Azikho izaziso"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Azikho izaziso ezintsha"</string>
- <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) -->
- <skip />
- <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) -->
- <skip />
+ <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Ukwehlisa umsindo wezaziso kuvuliwe"</string>
+ <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Ivolumu yedivayisi yakho kanye nezexwayiso kuncishiswa ngokuzenzakalelayo imizuzu efika kwemi-2 lapho uthola izaziso eziningi kakhulu ngesikhathi esisodwa."</string>
<string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Vala"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Vula ukuze ubone izaziso ezindala"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Le divayisi iphethwe ngumzali wakho"</string>
@@ -1226,7 +1232,6 @@
<string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Ukufakazela ubuqiniso budingekile. Thinta inzwa yezigxivizo zeminwe ukuze uqinisekise."</string>
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ikholi yefoni eqhubekayo"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Idatha yeselula"</string>
- <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Ixhunyiwe"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Ixhume okwesikhashana"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Uxhumo olungeluhle"</string>
@@ -1380,7 +1385,10 @@
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Kwenziwe"</string>
<string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Umsebenzi omuhle!"</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Buyela emuva"</string>
- <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Ukuze ubuyele emuva, swayiphela kwesokunxele noma kwesokudla usebenzisa iminwe emithathu noma yikuphi ephedini yokuthinta."</string>
+ <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) -->
+ <skip />
+ <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) -->
+ <skip />
<string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Iphedi yokuthinta ebonisa iminwe emithathu iya kwesokudla nakwesokunxele"</string>
<string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Isikrini sedivayisi esibonisa opopayi bokuthinta kwasemuva"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Ilambu lekhibhodi"</string>
@@ -1388,28 +1396,16 @@
<string name="home_controls_dream_label" msgid="6567105701292324257">"Izilawuli Zasekhaya"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Finyelela ngokushesha izilawuli zakho zasekhaya njengesigcini-skrini"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Hlehlisa"</string>
- <!-- no translation found for back_edu_toast_content (4530314597378982956) -->
- <skip />
- <!-- no translation found for home_edu_toast_content (3381071147871955415) -->
- <skip />
- <!-- no translation found for overview_edu_toast_content (5797030644017804518) -->
- <skip />
- <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) -->
- <skip />
- <!-- no translation found for back_edu_notification_title (5624780717751357278) -->
- <skip />
- <!-- no translation found for back_edu_notification_content (2497557451540954068) -->
- <skip />
- <!-- no translation found for home_edu_notification_title (6097902076909654045) -->
- <skip />
- <!-- no translation found for home_edu_notification_content (6631697734535766588) -->
- <skip />
- <!-- no translation found for overview_edu_notification_title (1265824157319562406) -->
- <skip />
- <!-- no translation found for overview_edu_notification_content (3578204677648432500) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_title (372262997265569063) -->
- <skip />
- <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) -->
- <skip />
+ <string name="back_edu_toast_content" msgid="4530314597378982956">"Ukuze ubuyele emuva, swayiphela kwesokunxele noma kwesokudla ngeminwe emithathu ephedini yokuthinta"</string>
+ <string name="home_edu_toast_content" msgid="3381071147871955415">"Ukuze uye ekhaya, swayiphela phezulu ngeminwe emithathu ephedini yokuthinta"</string>
+ <string name="overview_edu_toast_content" msgid="5797030644017804518">"Ukuze ubuke ama-app akamuva, swayiphela phezulu bese ubambe ngeminwe emithathu ephedini yokuthinta"</string>
+ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Ukuze ubuke wonke ama-app wakho, cindezela inkinobho yokufinyelela kukhibhodi yakho"</string>
+ <string name="back_edu_notification_title" msgid="5624780717751357278">"Sebenzisa iphedi yokuthinta ukuze ubuyele emuva"</string>
+ <string name="back_edu_notification_content" msgid="2497557451540954068">"Swayiphela kwesokunxele noma kwesokudla usebenzisa iminwe emithathu. Thepha ukuze ufunde kabanzi ngokunyakazisa umzimba."</string>
+ <string name="home_edu_notification_title" msgid="6097902076909654045">"Sebenzisa iphedi yokuthinta ukuya ekhaya"</string>
+ <string name="home_edu_notification_content" msgid="6631697734535766588">"Swayiphela phezulu usebenzisa iminwe emithathu. Thepha ukuze ufunde kabanzi ngokunyakazisa umzimba."</string>
+ <string name="overview_edu_notification_title" msgid="1265824157319562406">"Sebenzisa iphedi yokuthinta ukuze ubuke ama-app akamuva"</string>
+ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swayiphela phezulu bese uyabamba usebenzisa iminwe emithathu. Thepha ukuze ufunde kabanzi ngokunyakazisa umzimba."</string>
+ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Sebenzisa ikhibhodi yakho ukubuka wonke ama-app"</string>
+ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Cindezela inkinobho yokufinyelela noma kunini. Thepha ukuze ufunde kabanzi ngokunyakazisa umzimba."</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/tiles_states_strings.xml b/packages/SystemUI/res/values-zu/tiles_states_strings.xml
index 4cd138d..a795ee8 100644
--- a/packages/SystemUI/res/values-zu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zu/tiles_states_strings.xml
@@ -56,11 +56,6 @@
<item msgid="5376619709702103243">"Valiwe"</item>
<item msgid="4875147066469902392">"Vuliwe"</item>
</string-array>
- <string-array name="tile_states_modes">
- <item msgid="7764936419245199023">"Ayitholakali"</item>
- <item msgid="2004750556637773692">"Ivaliwe"</item>
- <item msgid="8968530753931637871">"Ivuliwe"</item>
- </string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"Akutholakali"</item>
<item msgid="5044688398303285224">"Valiwe"</item>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index c29c236..f0c8894 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -1050,4 +1050,7 @@
<!-- Only applicable for dual shade - Allow Notifications/QS shade to anchor to the bottom. -->
<bool name="config_dualShadeAlignedToBottom">false</bool>
+
+ <!-- List of packages for which we want to use activity info (instead of application info) for biometric prompt logo. Empty for AOSP. [DO NOT TRANSLATE] -->
+ <string-array name="config_useActivityLogoForBiometricPrompt" translatable="false"/>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index eda7bb0..e5750d2 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1729,10 +1729,18 @@
<dimen name="wallet_button_vertical_padding">8dp</dimen>
<!-- Ongoing activity chip -->
+ <!-- The activity chip side padding, used with the default phone icon. -->
<dimen name="ongoing_activity_chip_side_padding">12dp</dimen>
+ <!-- The activity chip side padding, used with an icon that has embedded padding (e.g. if the icon comes from the notification's smallIcon field). If the icon has padding, the chip itself can have less padding. -->
+ <dimen name="ongoing_activity_chip_side_padding_for_embedded_padding_icon">6dp</dimen>
+ <!-- The icon size, used with the default phone icon. -->
<dimen name="ongoing_activity_chip_icon_size">16dp</dimen>
- <!-- The padding between the icon and the text. -->
+ <!-- The icon size, used with an icon that has embedded padding. (If the icon has embedded padding, we need to make the whole icon larger so the icon itself doesn't look small.) -->
+ <dimen name="ongoing_activity_chip_embedded_padding_icon_size">22dp</dimen>
+ <!-- The padding between the icon and the text. Only used if the default phone icon is used. -->
<dimen name="ongoing_activity_chip_icon_text_padding">4dp</dimen>
+ <!-- The end padding for the timer text view. Only used if an embedded padding icon is used. -->
+ <dimen name="ongoing_activity_chip_text_end_padding_for_embedded_padding_icon">6dp</dimen>
<dimen name="ongoing_activity_chip_corner_radius">28dp</dimen>
<!-- Status bar user chip -->
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 212dae2..e4f900d 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -132,6 +132,7 @@
<!-- Status bar -->
<item type="id" name="status_bar_dot" />
+ <item type="id" name="ongoing_activity_chip_custom_icon" />
<!-- Default display cutout on the physical top of screen -->
<item type="id" name="display_cutout" />
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index ba37d58..159fb2e 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -432,8 +432,6 @@
<!-- Content description for the app logo icon on biometric prompt. [CHAR LIMIT=NONE] -->
<string name="biometric_dialog_logo">App logo</string>
- <!-- List of packages for which we want to show overridden logo. For example, an app overrides its launcher logo, if it's in this array, biometric dialog shows the overridden logo; otherwise biometric dialog still shows the default application info icon. [CHAR LIMIT=NONE] -->
- <string-array name="biometric_dialog_package_names_for_logo_with_overrides" />
<!-- Message shown when a biometric is authenticated, asking the user to confirm authentication [CHAR LIMIT=30] -->
<string name="biometric_dialog_confirm">Confirm</string>
<!-- Button name on BiometricPrompt shown when a biometric is detected but not authenticated. Tapping the button resumes authentication [CHAR LIMIT=30] -->
@@ -1381,11 +1379,15 @@
<!-- Casting that launched by SysUI (i.e. when there is no app name) -->
<!-- System casting media projection permission dialog title. [CHAR LIMIT=100] -->
- <string name="media_projection_entry_cast_permission_dialog_title">Start casting?</string>
+ <string name="media_projection_entry_cast_permission_dialog_title">Cast your screen?</string>
+ <!-- System casting media projection permission option for capturing just a single app [CHAR LIMIT=50] -->
+ <string name="media_projection_entry_cast_permission_dialog_option_text_single_app">Cast one app</string>
+ <!-- System casting media projection permission option for capturing the whole screen [CHAR LIMIT=50] -->
+ <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen">Cast entire screen</string>
<!-- System casting media projection permission warning for capturing the whole screen when SysUI casting requests it. [CHAR LIMIT=350] -->
- <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen">When you’re casting, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
+ <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen">When you’re casting your entire screen, anything on your screen is visible. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
<!-- System casting media projection permission warning for capturing a single app when SysUI casting requests it. [CHAR LIMIT=350] -->
- <string name="media_projection_entry_cast_permission_dialog_warning_single_app">When you’re casting an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
+ <string name="media_projection_entry_cast_permission_dialog_warning_single_app">When you’re casting an app, anything shown or played in that app is visible. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
<!-- System casting media projection permission button to continue for SysUI casting. [CHAR LIMIT=60] -->
<string name="media_projection_entry_cast_permission_dialog_continue">Start casting</string>
@@ -3649,6 +3651,8 @@
hasn't typed in anything in the search box yet. The helper is a component that shows the
user which keyboard shortcuts they can use. [CHAR LIMIT=NONE] -->
<string name="shortcut_helper_search_placeholder">Search shortcuts</string>
+ <!-- Text shown when a search query didn't produce any results. [CHAR LIMIT=NONE] -->
+ <string name="shortcut_helper_no_search_results">No search results</string>
<!-- Content description of the icon that allows to collapse a keyboard shortcut helper category
panel. The helper is a component that shows the user which keyboard shortcuts they can
use. The helper shows shortcuts in categories, which can be collapsed or expanded.
@@ -3709,6 +3713,11 @@
<!-- Education toast text for All Apps [CHAR_LIMIT=100] -->
<string name="all_apps_edu_toast_content">To view all your apps, press the action key on your keyboard</string>
+ <!-- Title of the one line view of a redacted notification -->
+ <string name="redacted_notification_single_line_title">Redacted</string>
+ <!-- Main text of the one line view of a redacted notification -->
+ <string name="redacted_notification_single_line_text">Unlock to view</string>
+
<!-- Education notification title for Back [CHAR_LIMIT=100] -->
<string name="back_edu_notification_title">Use your touchpad to go back</string>
<!-- Education notification text for Back [CHAR_LIMIT=100] -->
@@ -3725,4 +3734,16 @@
<string name="all_apps_edu_notification_title">Use your keyboard to view all apps</string>
<!-- Education notification text for All Apps [CHAR_LIMIT=100] -->
<string name="all_apps_edu_notification_content">Press the action key at any time. Tap to learn more gestures.</string>
+
+ <!-- Title for Extra Dim dialog [CHAR LIMIT=NONE] -->
+ <string name="accessibility_deprecate_extra_dim_dialog_title">Extra dim is now part of the brightness bar</string>
+ <!-- Content description for Extra Dim dialog. This helps users understand that we could make screen much dimmer by lowering the brightness through the brightness bar in a dark environment. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_deprecate_extra_dim_dialog_description">
+ You can now make the screen extra dim by lowering the brightness level even further from the top of your screen.\n\nThis works best when you\'re in a dark environment.
+ </string>
+ <!-- Label for button removing Extra Dim shortcuts [CHAR LIMIT=NONE] -->
+ <string name="accessibility_deprecate_extra_dim_dialog_button">Remove extra dim shortcut</string>
+ <!-- Toast message for notifying users to use regular brightness bar to lower the brightness. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_deprecate_extra_dim_dialog_toast">
+ Extra dim shortcut removed. To lower your brightness, use the regular brightness bar.</string>
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index c428705d..7fa7088 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -192,11 +192,10 @@
<style name="TextAppearance.AuthCredential.LogoDescription" parent="TextAppearance.Material3.LabelLarge" >
<item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
- <item name="android:ellipsize">marquee</item>
<item name="android:gravity">@integer/biometric_dialog_text_gravity</item>
- <item name="android:marqueeRepeatLimit">1</item>
- <item name="android:singleLine">true</item>
+ <item name="android:maxLines">1</item>
<item name="android:textColor">?androidprv:attr/materialColorOnSurfaceVariant</item>
+ <item name="android:ellipsize">end</item>
</style>
<style name="TextAppearance.AuthCredential.Title" parent="TextAppearance.Material3.HeadlineSmall" >
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 4217820..bf905db 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -647,7 +647,12 @@
@Override
public void onFinishInflate() {
super.onFinishInflate();
+ updateSecurityViewFlipper();
+ }
+
+ protected void updateSecurityViewFlipper() {
mSecurityViewFlipper = findViewById(R.id.view_flipper);
+ setupViewMode();
}
@Override
@@ -1004,10 +1009,10 @@
if (mUserSwitcherViewGroup == null) {
inflateUserSwitcher();
+ setupUserSwitcher();
+ mUserSwitcherController.addUserSwitchCallback(mUserSwitchCallback);
}
updateSecurityViewLocation();
- setupUserSwitcher();
- mUserSwitcherController.addUserSwitchCallback(mUserSwitchCallback);
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 93ee179..afd42cb 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -164,11 +164,6 @@
}
mCurrentUser = mSelectedUserInteractor.getSelectedUserId();
showPrimarySecurityScreen(false);
- if (mCurrentSecurityMode != SimPin
- && mCurrentSecurityMode != SimPuk) {
- reinflateViewFlipper((l) -> {
- });
- }
}
};
@@ -375,8 +370,7 @@
@Override
public void onDensityOrFontScaleChanged() {
- KeyguardSecurityContainerController.this
- .onDensityOrFontScaleOrOrientationChanged();
+ mView.onDensityOrFontScaleChanged();
}
@Override
@@ -1227,11 +1221,6 @@
mView.reloadColors();
}
- /** Handles density or font scale changes. */
- private void onDensityOrFontScaleOrOrientationChanged() {
- reinflateViewFlipper(controller -> mView.onDensityOrFontScaleChanged());
- }
-
/**
* Reinflate the view flipper child view.
*/
@@ -1239,7 +1228,10 @@
KeyguardSecurityViewFlipperController.OnViewInflatedCallback onViewInflatedListener) {
mSecurityViewFlipperController.clearViews();
mSecurityViewFlipperController.asynchronouslyInflateView(mCurrentSecurityMode,
- mKeyguardSecurityCallback, onViewInflatedListener);
+ mKeyguardSecurityCallback, (controller) -> {
+ mView.updateSecurityViewFlipper();
+ onViewInflatedListener.onViewInflated(controller);
+ });
}
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index d848602..073f33fe 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -33,7 +33,6 @@
import com.android.systemui.shade.TouchLogger;
import com.android.systemui.statusbar.CrossFadeHelper;
-import java.io.PrintWriter;
import java.util.Set;
/**
@@ -117,18 +116,6 @@
return TouchLogger.logDispatchTouch(TAG, ev, super.dispatchTouchEvent(ev));
}
- public void dump(PrintWriter pw, String[] args) {
- pw.println("KeyguardStatusView:");
- pw.println(" mDarkAmount: " + mDarkAmount);
- pw.println(" visibility: " + getVisibility());
- if (mClockView != null) {
- mClockView.dump(pw, args);
- }
- if (mKeyguardSlice != null) {
- mKeyguardSlice.dump(pw, args);
- }
- }
-
@Override
public ViewPropertyAnimator animate() {
if (Build.IS_DEBUGGABLE) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 603a47e..63a4af9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -48,9 +48,7 @@
import com.android.internal.jank.InteractionJankMonitor;
import com.android.keyguard.KeyguardClockSwitch.ClockSize;
import com.android.keyguard.logging.KeyguardLogger;
-import com.android.systemui.Dumpable;
import com.android.systemui.animation.ViewHierarchyAnimator;
-import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.MigrateClocksToBlueprint;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.plugins.clocks.ClockController;
@@ -70,15 +68,12 @@
import kotlin.coroutines.CoroutineContext;
import kotlin.coroutines.EmptyCoroutineContext;
-import java.io.PrintWriter;
-
import javax.inject.Inject;
/**
* Injectable controller for {@link KeyguardStatusView}.
*/
-public class KeyguardStatusViewController extends ViewController<KeyguardStatusView> implements
- Dumpable {
+public class KeyguardStatusViewController extends ViewController<KeyguardStatusView> {
private static final boolean DEBUG = KeyguardConstants.DEBUG;
@VisibleForTesting static final String TAG = "KeyguardStatusViewController";
private static final long STATUS_AREA_HEIGHT_ANIMATION_MILLIS = 133;
@@ -108,7 +103,6 @@
private Boolean mSplitShadeEnabled = false;
private Boolean mStatusViewCentered = true;
- private DumpManager mDumpManager;
private final TransitionListenerAdapter mKeyguardStatusAlignmentTransitionListener =
new TransitionListenerAdapter() {
@@ -176,7 +170,6 @@
KeyguardLogger logger,
InteractionJankMonitor interactionJankMonitor,
KeyguardInteractor keyguardInteractor,
- DumpManager dumpManager,
PowerInteractor powerInteractor) {
super(keyguardStatusView);
mKeyguardSliceViewController = keyguardSliceViewController;
@@ -188,7 +181,6 @@
dozeParameters, screenOffAnimationController, /* animateYPos= */ true,
logger.getBuffer());
mInteractionJankMonitor = interactionJankMonitor;
- mDumpManager = dumpManager;
mKeyguardInteractor = keyguardInteractor;
mPowerInteractor = powerInteractor;
}
@@ -222,7 +214,6 @@
});
}
- mDumpManager.registerDumpable(getInstanceName(), this);
if (MigrateClocksToBlueprint.isEnabled()) {
startCoroutines(EmptyCoroutineContext.INSTANCE);
mView.setVisibility(View.GONE);
@@ -276,13 +267,6 @@
}
/**
- * Called in notificationPanelViewController to avoid leak
- */
- public void onDestroy() {
- mDumpManager.unregisterDumpable(getInstanceName());
- }
-
- /**
* Updates views on doze time tick.
*/
public void dozeTimeTick() {
@@ -604,11 +588,6 @@
return mKeyguardClockSwitchController.getClock();
}
- @Override
- public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
- mView.dump(pw, args);
- }
-
String getInstanceName() {
return TAG + "#" + hashCode();
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/extradim/ExtraDimDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/accessibility/extradim/ExtraDimDialogDelegate.kt
new file mode 100644
index 0000000..fcb1206
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/extradim/ExtraDimDialogDelegate.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.accessibility.extradim
+
+import android.content.Context
+import android.content.DialogInterface
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.accessibility.AccessibilityManager
+import android.widget.Toast
+import com.android.internal.accessibility.AccessibilityShortcutController
+import com.android.internal.accessibility.common.ShortcutConstants
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.res.R
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+/** Dialog for removing Extra Dim shortcuts. */
+class ExtraDimDialogDelegate
+@Inject
+constructor(
+ private val context: Context,
+ @Application private val applicationScope: CoroutineScope,
+ @Background private val backgroundDispatcher: CoroutineDispatcher,
+ private val systemUIDialogFactory: SystemUIDialog.Factory,
+ private val accessibilityManager: AccessibilityManager,
+ private val userTracker: UserTracker,
+) : SystemUIDialog.Delegate {
+
+ private val onClickListener: DialogInterface.OnClickListener =
+ DialogInterface.OnClickListener { dialog, _ ->
+ applicationScope.launch {
+ dialog.dismiss()
+ onRemoveExtraDimShortcutButtonClicked()
+ Toast.makeText(
+ context,
+ context.getText(R.string.accessibility_deprecate_extra_dim_dialog_toast),
+ Toast.LENGTH_LONG
+ )
+ .show()
+ }
+ }
+
+ override fun beforeCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
+ dialog.setTitle(R.string.accessibility_deprecate_extra_dim_dialog_title)
+ dialog.setView(
+ LayoutInflater.from(dialog.context)
+ .inflate(R.layout.accessibility_deprecate_extra_dim_dialog, null)
+ )
+ dialog.setPositiveButton(
+ R.string.accessibility_deprecate_extra_dim_dialog_button,
+ onClickListener
+ )
+ }
+
+ override fun createDialog(): SystemUIDialog {
+ val dialog = systemUIDialogFactory.create(this)
+ dialog.setCanceledOnTouchOutside(false)
+ return dialog
+ }
+
+ private suspend fun onRemoveExtraDimShortcutButtonClicked() =
+ withContext(backgroundDispatcher) {
+ accessibilityManager.enableShortcutsForTargets(
+ /* enable= */ false,
+ ShortcutConstants.UserShortcutType.ALL,
+ setOf(
+ AccessibilityShortcutController.REDUCE_BRIGHT_COLORS_COMPONENT_NAME
+ .flattenToString()
+ ),
+ userTracker.userId
+ )
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/extradim/ExtraDimDialogManager.kt b/packages/SystemUI/src/com/android/systemui/accessibility/extradim/ExtraDimDialogManager.kt
new file mode 100644
index 0000000..e1297d3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/extradim/ExtraDimDialogManager.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.accessibility.extradim
+
+import androidx.annotation.VisibleForTesting
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import javax.inject.Inject
+import javax.inject.Provider
+
+/** Managing the Extra Dim Dialog behaviors. */
+@SysUISingleton
+class ExtraDimDialogManager
+@Inject
+constructor(
+ private val extraDimDialogDelegateProvider: Provider<ExtraDimDialogDelegate>,
+ private val mActivityStarter: ActivityStarter
+) {
+ private var dialog: SystemUIDialog? = null
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+ fun dismissKeyguardIfNeededAndShowDialog() {
+ mActivityStarter.executeRunnableDismissingKeyguard(
+ { showRemoveExtraDimShortcutsDialog() },
+ /* cancelAction= */ null,
+ /* dismissShade= */ false,
+ /* afterKeyguardGone= */ true,
+ /* deferred= */ false
+ )
+ }
+
+ /** Show the dialog for removing all Extra Dim shortcuts. */
+ private fun showRemoveExtraDimShortcutsDialog() {
+ dialog?.dismiss()
+ dialog = extraDimDialogDelegateProvider.get().createDialog()
+ dialog!!.show()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/extradim/ExtraDimDialogReceiver.kt b/packages/SystemUI/src/com/android/systemui/accessibility/extradim/ExtraDimDialogReceiver.kt
new file mode 100644
index 0000000..405993a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/extradim/ExtraDimDialogReceiver.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.accessibility.extradim
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import com.android.server.display.feature.flags.Flags
+import javax.inject.Inject
+
+/**
+ * BroadcastReceiver for handling [ExtraDimDialogDelegate] intent.
+ *
+ * This is not exported. Need to call from framework and use SYSTEM user to send the intent.
+ */
+class ExtraDimDialogReceiver
+@Inject
+constructor(
+ private val extraDimDialogManager: ExtraDimDialogManager,
+) : BroadcastReceiver() {
+
+ override fun onReceive(context: Context, intent: Intent) {
+ if (
+ !Flags.evenDimmer() ||
+ !context
+ .getResources()
+ .getBoolean(com.android.internal.R.bool.config_evenDimmerEnabled)
+ ) {
+ return
+ }
+
+ if (ACTION == intent.action) {
+ extraDimDialogManager.dismissKeyguardIfNeededAndShowDialog()
+ }
+ }
+
+ companion object {
+ const val ACTION = "com.android.systemui.action.LAUNCH_REMOVE_EXTRA_DIM_DIALOG"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 430ff07..9521be1 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -65,9 +65,6 @@
import android.window.OnBackInvokedDispatcher;
import androidx.constraintlayout.widget.ConstraintLayout;
-import androidx.core.view.AccessibilityDelegateCompat;
-import androidx.core.view.ViewCompat;
-import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import com.android.app.animation.Interpolators;
import com.android.internal.annotations.VisibleForTesting;
@@ -385,19 +382,6 @@
mBiometricScrollView = mLayout.findViewById(R.id.biometric_scrollview);
addView(mLayout);
mBackgroundView = mLayout.findViewById(R.id.background);
- ViewCompat.setAccessibilityDelegate(mBackgroundView, new AccessibilityDelegateCompat() {
- @Override
- public void onInitializeAccessibilityNodeInfo(View host,
- AccessibilityNodeInfoCompat info) {
- super.onInitializeAccessibilityNodeInfo(host, info);
- info.addAction(
- new AccessibilityNodeInfoCompat.AccessibilityActionCompat(
- AccessibilityNodeInfoCompat.ACTION_CLICK,
- mContext.getString(R.string.biometric_dialog_cancel_authentication)
- )
- );
- }
- });
mPanelView = mLayout.findViewById(R.id.panel);
if (!constraintBp()) {
@@ -428,7 +412,6 @@
});
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
- setFocusableInTouchMode(true);
requestFocus();
}
@@ -480,7 +463,8 @@
}
}
- private void onBackInvoked() {
+ @VisibleForTesting
+ public void onBackInvoked() {
sendEarlyUserCanceled();
animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepository.kt b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepository.kt
index ca03a00..da270c0 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepository.kt
@@ -39,7 +39,6 @@
import com.android.systemui.biometrics.shared.model.AuthenticationReason.SettingsOperations
import com.android.systemui.biometrics.shared.model.AuthenticationState
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
-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.keyguard.shared.model.AcquiredFingerprintAuthenticationStatus
@@ -49,6 +48,7 @@
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterIsInstance
@@ -85,7 +85,7 @@
* onAcquired in [FingerprintManager.EnrollmentCallback] and [FaceManager.EnrollmentCallback]
*/
private val authenticationState: Flow<AuthenticationState> =
- conflatedCallbackFlow {
+ callbackFlow {
val updateAuthenticationState = { state: AuthenticationState ->
Log.d(TAG, "authenticationState updated: $state")
trySendWithFailureLogging(state, TAG, "Error sending AuthenticationState state")
@@ -169,7 +169,9 @@
}
}
- updateAuthenticationState(AuthenticationState.Idle(AuthenticationReason.NotRunning))
+ updateAuthenticationState(
+ AuthenticationState.Idle(requestReason = AuthenticationReason.NotRunning)
+ )
biometricManager?.registerAuthenticationStateListener(authenticationStateListener)
awaitClose {
biometricManager?.unregisterAuthenticationStateListener(
@@ -180,23 +182,32 @@
.distinctUntilChanged()
.shareIn(applicationScope, started = SharingStarted.Eagerly, replay = 1)
- override val fingerprintAuthenticationReason: Flow<AuthenticationReason> =
+ private val fingerprintAuthenticationState: Flow<AuthenticationState> =
authenticationState
.filter {
- it is AuthenticationState.Idle ||
- (it is AuthenticationState.Started &&
- it.biometricSourceType == BiometricSourceType.FINGERPRINT) ||
- (it is AuthenticationState.Stopped &&
- it.biometricSourceType == BiometricSourceType.FINGERPRINT)
+ it.biometricSourceType == null ||
+ it.biometricSourceType == BiometricSourceType.FINGERPRINT
}
+ .onEach { Log.d(TAG, "fingerprintAuthenticationState updated: $it") }
+
+ private val fingerprintRunningState: Flow<AuthenticationState> =
+ fingerprintAuthenticationState
+ .filter {
+ it is AuthenticationState.Idle ||
+ it is AuthenticationState.Started ||
+ it is AuthenticationState.Stopped
+ }
+ .onEach { Log.d(TAG, "fingerprintRunningState updated: $it") }
+
+ override val fingerprintAuthenticationReason: Flow<AuthenticationReason> =
+ fingerprintRunningState
.map { it.requestReason }
.onEach { Log.d(TAG, "fingerprintAuthenticationReason updated: $it") }
override val fingerprintAcquiredStatus: Flow<FingerprintAuthenticationStatus> =
- authenticationState
- .filterIsInstance<AuthenticationState.Acquired>()
- .filter { it.biometricSourceType == BiometricSourceType.FINGERPRINT }
- .map { AcquiredFingerprintAuthenticationStatus(it.requestReason, it.acquiredInfo) }
+ fingerprintAuthenticationState.filterIsInstance<AuthenticationState.Acquired>().map {
+ AcquiredFingerprintAuthenticationStatus(it.requestReason, it.acquiredInfo)
+ }
companion object {
private const val TAG = "BiometricStatusRepositoryImpl"
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/AuthenticationState.kt b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/AuthenticationState.kt
index 5ceae36..81ea6a9 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/AuthenticationState.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/AuthenticationState.kt
@@ -27,6 +27,9 @@
* authentication.
*/
sealed interface AuthenticationState {
+ /** Indicates [BiometricSourceType] of authentication state update, null in idle auth state. */
+ val biometricSourceType: BiometricSourceType?
+
/**
* Indicates [AuthenticationReason] from [BiometricRequestConstants.RequestReason] for
* requesting auth
@@ -43,7 +46,7 @@
* message.
*/
data class Acquired(
- val biometricSourceType: BiometricSourceType,
+ override val biometricSourceType: BiometricSourceType,
override val requestReason: AuthenticationReason,
val acquiredInfo: Int
) : AuthenticationState
@@ -59,7 +62,7 @@
* @param requestReason reason from [BiometricRequestConstants.RequestReason] for authentication
*/
data class Error(
- val biometricSourceType: BiometricSourceType,
+ override val biometricSourceType: BiometricSourceType,
val errString: String?,
val errCode: Int,
override val requestReason: AuthenticationReason,
@@ -73,7 +76,7 @@
* @param userId The user id for the requested authentication
*/
data class Failed(
- val biometricSourceType: BiometricSourceType,
+ override val biometricSourceType: BiometricSourceType,
override val requestReason: AuthenticationReason,
val userId: Int
) : AuthenticationState
@@ -87,7 +90,7 @@
* @param requestReason reason from [BiometricRequestConstants.RequestReason] for authentication
*/
data class Help(
- val biometricSourceType: BiometricSourceType,
+ override val biometricSourceType: BiometricSourceType,
val helpString: String?,
val helpCode: Int,
override val requestReason: AuthenticationReason,
@@ -96,9 +99,13 @@
/**
* Authentication state when no auth is running
*
+ * @param biometricSourceType null
* @param requestReason [AuthenticationReason.NotRunning]
*/
- data class Idle(override val requestReason: AuthenticationReason) : AuthenticationState
+ data class Idle(
+ override val biometricSourceType: BiometricSourceType? = null,
+ override val requestReason: AuthenticationReason
+ ) : AuthenticationState
/**
* AuthenticationState when auth is started
@@ -107,7 +114,7 @@
* @param requestReason reason from [BiometricRequestConstants.RequestReason] for authentication
*/
data class Started(
- val biometricSourceType: BiometricSourceType,
+ override val biometricSourceType: BiometricSourceType,
override val requestReason: AuthenticationReason
) : AuthenticationState
@@ -118,7 +125,7 @@
* @param requestReason [AuthenticationReason.NotRunning]
*/
data class Stopped(
- val biometricSourceType: BiometricSourceType,
+ override val biometricSourceType: BiometricSourceType,
override val requestReason: AuthenticationReason
) : AuthenticationState
@@ -131,7 +138,7 @@
* @param userId The user id for the requested authentication
*/
data class Succeeded(
- val biometricSourceType: BiometricSourceType,
+ override val biometricSourceType: BiometricSourceType,
val isStrongBiometric: Boolean,
override val requestReason: AuthenticationReason,
val userId: Int
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
index ecfbd66..2d525aa 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
@@ -34,6 +34,10 @@
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
+import androidx.core.view.AccessibilityDelegateCompat
+import androidx.core.view.ViewCompat
+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
@@ -63,6 +67,7 @@
import kotlinx.coroutines.launch
private const val TAG = "BiometricViewBinder"
+private const val MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER = 30
/** Top-most view binder for BiometricPrompt views. */
object BiometricViewBinder {
@@ -124,7 +129,6 @@
subtitleView.isSelected =
!accessibilityManager.isEnabled || !accessibilityManager.isTouchExplorationEnabled
- val iconOverlayView = view.requireViewById<LottieAnimationView>(R.id.biometric_icon_overlay)
val iconView = view.requireViewById<LottieAnimationView>(R.id.biometric_icon)
val iconSizeOverride =
@@ -145,6 +149,25 @@
val confirmationButton = view.requireViewById<Button>(R.id.button_confirm)
val retryButton = view.requireViewById<Button>(R.id.button_try_again)
+ // Handles custom "Cancel Authentication" talkback action
+ val cancelDelegate: AccessibilityDelegateCompat =
+ object : AccessibilityDelegateCompat() {
+ override fun onInitializeAccessibilityNodeInfo(
+ host: View,
+ info: AccessibilityNodeInfoCompat
+ ) {
+ super.onInitializeAccessibilityNodeInfo(host, info)
+ info.addAction(
+ AccessibilityActionCompat(
+ AccessibilityNodeInfoCompat.ACTION_CLICK,
+ view.context.getString(R.string.biometric_dialog_cancel_authentication)
+ )
+ )
+ }
+ }
+ ViewCompat.setAccessibilityDelegate(backgroundView, cancelDelegate)
+ ViewCompat.setAccessibilityDelegate(cancelButton, cancelDelegate)
+
// TODO(b/330788871): temporary workaround for the unsafe callbacks & legacy controllers
val adapter =
Spaghetti(
@@ -161,19 +184,31 @@
// these do not change and need to be set before any size transitions
val modalities = viewModel.modalities.first()
- if (modalities.hasFingerprint) {
- /**
- * Load the given [rawResources] immediately so they are cached for use in the
- * [context].
- */
- val rawResources = viewModel.iconViewModel.getRawAssets(modalities.hasSfps)
- for (res in rawResources) {
- LottieCompositionFactory.fromRawRes(view.context, res)
+ /**
+ * Load the given [rawResources] immediately so they are cached for use in the
+ * [context].
+ */
+ val rawResources =
+ if (modalities.hasFaceAndFingerprint) {
+ viewModel.iconViewModel.getCoexAssetsList(modalities.hasSfps)
+ } else if (modalities.hasFingerprintOnly) {
+ viewModel.iconViewModel.getFingerprintAssetsList(modalities.hasSfps)
+ } else if (modalities.hasFaceOnly) {
+ viewModel.iconViewModel.getFaceAssetsList()
+ } else {
+ listOf()
}
+
+ for (res in rawResources) {
+ LottieCompositionFactory.fromRawRes(view.context, res)
}
- logoView.setImageDrawable(viewModel.logo.first())
- logoDescriptionView.text = viewModel.logoDescription.first()
+ val logoInfo = viewModel.logoInfo.first()
+ logoView.setImageDrawable(logoInfo.first)
+ // The ellipsize effect on xml happens only when the TextView does not have any free
+ // space on the screen to show the text. So we need to manually truncate.
+ logoDescriptionView.text =
+ logoInfo.second?.ellipsize(MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER)
titleView.text = viewModel.title.first()
subtitleView.text = viewModel.subtitle.first()
descriptionView.text = viewModel.description.first()
@@ -240,7 +275,6 @@
if (!showWithoutIcon) {
PromptIconViewBinder.bind(
iconView,
- iconOverlayView,
iconSizeOverride,
viewModel,
)
@@ -364,10 +398,7 @@
else -> null
}
}
- .collect { onTouch ->
- iconOverlayView.setOnTouchListener(onTouch)
- iconView.setOnTouchListener(onTouch)
- }
+ .collect { onTouch -> iconView.setOnTouchListener(onTouch) }
}
// dismiss prompt when authenticated and confirmed
@@ -382,11 +413,12 @@
backgroundView.importantForAccessibility =
IMPORTANT_FOR_ACCESSIBILITY_NO
- // Allow icon to be used as confirmation button with a11y enabled
- if (accessibilityManager.isTouchExplorationEnabled) {
- iconOverlayView.setOnClickListener {
- viewModel.confirmAuthenticated()
- }
+ // Allow icon to be used as confirmation button with udfps and a11y
+ // enabled
+ if (
+ accessibilityManager.isTouchExplorationEnabled &&
+ modalities.hasUdfps
+ ) {
iconView.setOnClickListener { viewModel.confirmAuthenticated() }
}
}
@@ -690,6 +722,9 @@
else -> ""
}
+private fun String.ellipsize(cutOffLength: Int) =
+ if (length <= cutOffLength) this else replaceRange(cutOffLength, length, "...")
+
private fun Boolean.asVisibleOrGone(): Int = if (this) View.VISIBLE else View.GONE
private fun Boolean.asVisibleOrHidden(): Int = if (this) View.VISIBLE else View.INVISIBLE
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
index a87ee24..b9ec2de 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
@@ -167,16 +167,13 @@
fun setVisibilities(hideSensorIcon: Boolean, size: PromptSize) {
viewsToHideWhenSmall.forEach { it.showContentOrHide(forceHide = size.isSmall) }
largeConstraintSet.setVisibility(iconHolderView.id, View.GONE)
- largeConstraintSet.setVisibility(R.id.biometric_icon_overlay, View.GONE)
largeConstraintSet.setVisibility(R.id.indicator, View.GONE)
largeConstraintSet.setVisibility(R.id.scrollView, View.GONE)
if (hideSensorIcon) {
smallConstraintSet.setVisibility(iconHolderView.id, View.GONE)
- smallConstraintSet.setVisibility(R.id.biometric_icon_overlay, View.GONE)
smallConstraintSet.setVisibility(R.id.indicator, View.GONE)
mediumConstraintSet.setVisibility(iconHolderView.id, View.GONE)
- mediumConstraintSet.setVisibility(R.id.biometric_icon_overlay, View.GONE)
mediumConstraintSet.setVisibility(R.id.indicator, View.GONE)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt
index 5e0e2bb..9e4aaaa 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt
@@ -17,6 +17,7 @@
package com.android.systemui.biometrics.ui.binder
+import android.content.res.Resources
import android.util.Log
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
@@ -29,8 +30,8 @@
import com.android.systemui.biometrics.ui.viewmodel.PromptViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.res.R
-import com.android.systemui.util.kotlin.Utils.Companion.toQuad
-import com.android.systemui.util.kotlin.Utils.Companion.toTriple
+import com.android.systemui.util.kotlin.Quad
+import com.android.systemui.util.kotlin.Utils.Companion.toQuint
import com.android.systemui.util.kotlin.sample
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
@@ -39,14 +40,10 @@
/** Sub-binder for [BiometricPromptLayout.iconView]. */
object PromptIconViewBinder {
- /**
- * Binds [BiometricPromptLayout.iconView] and [BiometricPromptLayout.biometric_icon_overlay] to
- * [PromptIconViewModel].
- */
+ /** Binds [BiometricPromptLayout.iconView] to [PromptIconViewModel]. */
@JvmStatic
fun bind(
iconView: LottieAnimationView,
- iconOverlayView: LottieAnimationView,
iconViewLayoutParamSizeOverride: Pair<Int, Int>?,
promptViewModel: PromptViewModel
) {
@@ -57,9 +54,6 @@
if (iconViewLayoutParamSizeOverride != null) {
iconView.layoutParams.width = iconViewLayoutParamSizeOverride.first
iconView.layoutParams.height = iconViewLayoutParamSizeOverride.second
-
- iconOverlayView.layoutParams.width = iconViewLayoutParamSizeOverride.first
- iconOverlayView.layoutParams.height = iconViewLayoutParamSizeOverride.second
}
if (!constraintBp()) {
@@ -95,9 +89,6 @@
if (iconViewLayoutParamSizeOverride == null) {
iconView.layoutParams.width = iconSize.first
iconView.layoutParams.height = iconSize.second
-
- iconOverlayView.layoutParams.width = iconSize.first
- iconOverlayView.layoutParams.height = iconSize.second
}
}
}
@@ -109,18 +100,25 @@
combine(
viewModel.activeAuthType,
viewModel.shouldAnimateIconView,
+ viewModel.shouldLoopIconView,
viewModel.showingError,
- ::Triple
+ ::Quad
),
- ::toQuad
+ ::toQuint
)
- .collect { (iconAsset, activeAuthType, shouldAnimateIconView, showingError)
- ->
+ .collect {
+ (
+ iconAsset,
+ activeAuthType,
+ shouldAnimateIconView,
+ shouldLoopIconView,
+ showingError) ->
if (iconAsset != -1) {
iconView.updateAsset(
"iconAsset",
iconAsset,
shouldAnimateIconView,
+ shouldLoopIconView,
activeAuthType
)
viewModel.setPreviousIconWasError(showingError)
@@ -129,34 +127,7 @@
}
launch {
- viewModel.iconOverlayAsset
- .sample(
- combine(
- viewModel.shouldAnimateIconOverlay,
- viewModel.showingError,
- ::Pair
- ),
- ::toTriple
- )
- .collect { (iconOverlayAsset, shouldAnimateIconOverlay, showingError) ->
- if (iconOverlayAsset != -1) {
- iconOverlayView.updateAsset(
- "iconOverlayAsset",
- iconOverlayAsset,
- shouldAnimateIconOverlay,
- AuthType.Fingerprint
- )
- viewModel.setPreviousIconOverlayWasError(showingError)
- }
- }
- }
-
- launch {
- viewModel.shouldFlipIconView.collect { shouldFlipIconView ->
- if (shouldFlipIconView) {
- iconView.rotation = 180f
- }
- }
+ viewModel.iconViewRotation.collect { rotation -> iconView.rotation = rotation }
}
launch {
@@ -171,97 +142,83 @@
}
}
-private val assetIdToString: Map<Int, String> =
- mapOf(
- // UDFPS assets
- R.raw.fingerprint_dialogue_error_to_fingerprint_lottie to
- "fingerprint_dialogue_error_to_fingerprint_lottie",
- R.raw.fingerprint_dialogue_error_to_success_lottie to
- "fingerprint_dialogue_error_to_success_lottie",
- R.raw.fingerprint_dialogue_fingerprint_to_error_lottie to
- "fingerprint_dialogue_fingerprint_to_error_lottie",
- R.raw.fingerprint_dialogue_fingerprint_to_success_lottie to
- "fingerprint_dialogue_fingerprint_to_success_lottie",
- // SFPS assets
- R.raw.biometricprompt_fingerprint_to_error_landscape to
- "biometricprompt_fingerprint_to_error_landscape",
- R.raw.biometricprompt_folded_base_bottomright to "biometricprompt_folded_base_bottomright",
- R.raw.biometricprompt_folded_base_default to "biometricprompt_folded_base_default",
- R.raw.biometricprompt_folded_base_topleft to "biometricprompt_folded_base_topleft",
- R.raw.biometricprompt_landscape_base to "biometricprompt_landscape_base",
- R.raw.biometricprompt_portrait_base_bottomright to
- "biometricprompt_portrait_base_bottomright",
- R.raw.biometricprompt_portrait_base_topleft to "biometricprompt_portrait_base_topleft",
- R.raw.biometricprompt_symbol_error_to_fingerprint_landscape to
- "biometricprompt_symbol_error_to_fingerprint_landscape",
- R.raw.biometricprompt_symbol_error_to_fingerprint_portrait_bottomright to
- "biometricprompt_symbol_error_to_fingerprint_portrait_bottomright",
- R.raw.biometricprompt_symbol_error_to_fingerprint_portrait_topleft to
- "biometricprompt_symbol_error_to_fingerprint_portrait_topleft",
- R.raw.biometricprompt_symbol_error_to_success_landscape to
- "biometricprompt_symbol_error_to_success_landscape",
- R.raw.biometricprompt_symbol_error_to_success_portrait_bottomright to
- "biometricprompt_symbol_error_to_success_portrait_bottomright",
- R.raw.biometricprompt_symbol_error_to_success_portrait_topleft to
- "biometricprompt_symbol_error_to_success_portrait_topleft",
- R.raw.biometricprompt_symbol_fingerprint_to_error_portrait_bottomright to
- "biometricprompt_symbol_fingerprint_to_error_portrait_bottomright",
- R.raw.biometricprompt_symbol_fingerprint_to_error_portrait_topleft to
- "biometricprompt_symbol_fingerprint_to_error_portrait_topleft",
- R.raw.biometricprompt_symbol_fingerprint_to_success_landscape to
- "biometricprompt_symbol_fingerprint_to_success_landscape",
- R.raw.biometricprompt_symbol_fingerprint_to_success_portrait_bottomright to
- "biometricprompt_symbol_fingerprint_to_success_portrait_bottomright",
- R.raw.biometricprompt_symbol_fingerprint_to_success_portrait_topleft to
- "biometricprompt_symbol_fingerprint_to_success_portrait_topleft",
- // Face assets
- R.raw.face_dialog_wink_from_dark to "face_dialog_wink_from_dark",
- R.raw.face_dialog_dark_to_checkmark to "face_dialog_dark_to_checkmark",
- R.raw.face_dialog_dark_to_error to "face_dialog_dark_to_error",
- R.raw.face_dialog_error_to_idle to "face_dialog_error_to_idle",
- R.raw.face_dialog_idle_static to "face_dialog_idle_static",
- R.raw.face_dialog_authenticating to "face_dialog_authenticating",
- // Co-ex assets
- R.raw.fingerprint_dialogue_unlocked_to_checkmark_success_lottie to
- "fingerprint_dialogue_unlocked_to_checkmark_success_lottie",
- R.raw.fingerprint_dialogue_error_to_unlock_lottie to
- "fingerprint_dialogue_error_to_unlock_lottie",
- R.raw.fingerprint_dialogue_fingerprint_to_unlock_lottie to
- "fingerprint_dialogue_fingerprint_to_unlock_lottie",
- )
-
-private fun getAssetNameFromId(id: Int): String {
- return assetIdToString.getOrDefault(id, "Asset $id not found")
-}
-
fun LottieAnimationView.updateAsset(
type: String,
asset: Int,
shouldAnimateIconView: Boolean,
+ shouldLoopIconView: Boolean,
activeAuthType: AuthType
) {
setFailureListener(type, asset, activeAuthType)
+ pauseAnimation()
setAnimation(asset)
- frame = 0
+ if (animatingFromSfpsAuthenticating(asset)) {
+ // Skipping to error / success / unlock segment of animation
+ setMinFrame(151)
+ } else {
+ frame = 0
+ }
if (shouldAnimateIconView) {
- if (asset == R.raw.face_dialog_authenticating) {
- loop(true)
- } else {
- loop(false)
- }
+ loop(shouldLoopIconView)
playAnimation()
}
LottieColorUtils.applyDynamicColors(context, this)
}
+private fun animatingFromSfpsAuthenticating(asset: Int): Boolean =
+ asset in sfpsFpToErrorAssets || asset in sfpsFpToUnlockAssets || asset in sfpsFpToSuccessAssets
+
+private val sfpsFpToErrorAssets: List<Int> =
+ listOf(
+ R.raw.biometricprompt_sfps_fingerprint_to_error,
+ R.raw.biometricprompt_sfps_fingerprint_to_error_90,
+ R.raw.biometricprompt_sfps_fingerprint_to_error_180,
+ R.raw.biometricprompt_sfps_fingerprint_to_error_270,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_error,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_error_90,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_error_180,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_error_270,
+ )
+
+private val sfpsFpToUnlockAssets: List<Int> =
+ listOf(
+ R.raw.biometricprompt_sfps_fingerprint_to_unlock,
+ R.raw.biometricprompt_sfps_fingerprint_to_unlock_90,
+ R.raw.biometricprompt_sfps_fingerprint_to_unlock_180,
+ R.raw.biometricprompt_sfps_fingerprint_to_unlock_270,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_unlock,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_unlock_90,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_unlock_180,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_unlock_270,
+ )
+
+private val sfpsFpToSuccessAssets: List<Int> =
+ listOf(
+ R.raw.biometricprompt_sfps_fingerprint_to_success,
+ R.raw.biometricprompt_sfps_fingerprint_to_success_90,
+ R.raw.biometricprompt_sfps_fingerprint_to_success_180,
+ R.raw.biometricprompt_sfps_fingerprint_to_success_270,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_success,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_success_90,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_success_180,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_success_270,
+ )
+
private fun LottieAnimationView.setFailureListener(type: String, asset: Int, authType: AuthType) {
+ val assetName =
+ try {
+ context.resources.getResourceEntryName(asset)
+ } catch (e: Resources.NotFoundException) {
+ "Asset $asset not found"
+ }
+
setFailureListener { result: Throwable? ->
Log.d(
TAG,
"Collecting $type | " +
"activeAuthType = $authType | " +
"Invalid resource id: $asset, " +
- "name ${getAssetNameFromId(asset)}",
+ "name $assetName",
result
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptIconViewModel.kt
index 6c83dac..574c40d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptIconViewModel.kt
@@ -19,11 +19,8 @@
import android.annotation.RawRes
import android.content.res.Configuration
-import android.graphics.Rect
-import android.util.RotationUtils
import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor
-import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
import com.android.systemui.biometrics.shared.model.DisplayRotation
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
import com.android.systemui.res.R
@@ -35,15 +32,11 @@
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
-/**
- * Models UI of [BiometricPromptLayout.iconView] and [BiometricPromptLayout.biometric_icon_overlay]
- */
-class PromptIconViewModel
-constructor(
+/** Models UI of [BiometricPromptLayout.iconView] */
+class PromptIconViewModel(
promptViewModel: PromptViewModel,
private val displayStateInteractor: DisplayStateInteractor,
promptSelectorInteractor: PromptSelectorInteractor,
- udfpsOverlayInteractor: UdfpsOverlayInteractor,
) {
/** Auth types for the UI to display. */
@@ -74,44 +67,16 @@
}
}
- val udfpsSensorBounds: Flow<Rect> =
- combine(
- udfpsOverlayInteractor.udfpsOverlayParams,
- displayStateInteractor.currentRotation
- ) { params, rotation ->
- val rotatedBounds = Rect(params.sensorBounds)
- RotationUtils.rotateBounds(
- rotatedBounds,
- params.naturalDisplayWidth,
- params.naturalDisplayHeight,
- rotation.ordinal
- )
- Rect(
- rotatedBounds.left,
- rotatedBounds.top,
- params.logicalDisplayWidth - rotatedBounds.right,
- params.logicalDisplayHeight - rotatedBounds.bottom
- )
- }
- .distinctUntilChanged()
-
/** Whether an error message is currently being shown. */
val showingError = promptViewModel.showingError
/** Whether the previous icon shown displayed an error. */
private val _previousIconWasError: MutableStateFlow<Boolean> = MutableStateFlow(false)
- /** Whether the previous icon overlay shown displayed an error. */
- private val _previousIconOverlayWasError: MutableStateFlow<Boolean> = MutableStateFlow(false)
-
fun setPreviousIconWasError(previousIconWasError: Boolean) {
_previousIconWasError.value = previousIconWasError
}
- fun setPreviousIconOverlayWasError(previousIconOverlayWasError: Boolean) {
- _previousIconOverlayWasError.value = previousIconOverlayWasError
- }
-
val iconSize: Flow<Pair<Int, Int>> =
combine(
promptViewModel.position,
@@ -133,7 +98,6 @@
AuthType.Fingerprint ->
combine(
displayStateInteractor.currentRotation,
- displayStateInteractor.isFolded,
displayStateInteractor.isInRearDisplayMode,
promptSelectorInteractor.fingerprintSensorType,
promptViewModel.isAuthenticated,
@@ -141,7 +105,6 @@
promptViewModel.showingError
) {
rotation: DisplayRotation,
- isFolded: Boolean,
isInRearDisplayMode: Boolean,
sensorType: FingerprintSensorType,
authState: PromptAuthState,
@@ -149,7 +112,13 @@
showingError: Boolean ->
when (sensorType) {
FingerprintSensorType.POWER_BUTTON ->
- getSfpsIconViewAsset(rotation, isFolded, isInRearDisplayMode)
+ getSfpsIconViewAsset(
+ rotation,
+ isInRearDisplayMode,
+ authState.isAuthenticated,
+ isAuthenticating,
+ showingError
+ )
else ->
getFingerprintIconViewAsset(
authState.isAuthenticated,
@@ -179,7 +148,6 @@
AuthType.Coex ->
combine(
displayStateInteractor.currentRotation,
- displayStateInteractor.isFolded,
displayStateInteractor.isInRearDisplayMode,
promptSelectorInteractor.fingerprintSensorType,
promptViewModel.isAuthenticated,
@@ -188,7 +156,6 @@
promptViewModel.showingError,
) {
rotation: DisplayRotation,
- isFolded: Boolean,
isInRearDisplayMode: Boolean,
sensorType: FingerprintSensorType,
authState: PromptAuthState,
@@ -197,7 +164,14 @@
showingError: Boolean ->
when (sensorType) {
FingerprintSensorType.POWER_BUTTON ->
- getSfpsIconViewAsset(rotation, isFolded, isInRearDisplayMode)
+ getCoexSfpsIconViewAsset(
+ rotation,
+ isInRearDisplayMode,
+ authState,
+ isAuthenticating,
+ isPendingConfirmation,
+ showingError
+ )
else ->
getCoexIconViewAsset(
authState,
@@ -214,8 +188,8 @@
isAuthenticated: Boolean,
isAuthenticating: Boolean,
showingError: Boolean
- ): Int =
- if (isAuthenticated) {
+ ): Int {
+ return if (isAuthenticated) {
if (_previousIconWasError.value) {
R.raw.fingerprint_dialogue_error_to_success_lottie
} else {
@@ -232,39 +206,34 @@
} else {
-1
}
+ }
@RawRes
private fun getSfpsIconViewAsset(
rotation: DisplayRotation,
- isDeviceFolded: Boolean,
isInRearDisplayMode: Boolean,
- ): Int =
- when (rotation) {
- DisplayRotation.ROTATION_90 ->
- if (isInRearDisplayMode) {
- R.raw.biometricprompt_rear_portrait_reverse_base
- } else if (isDeviceFolded) {
- R.raw.biometricprompt_folded_base_topleft
- } else {
- R.raw.biometricprompt_portrait_base_topleft
- }
- DisplayRotation.ROTATION_270 ->
- if (isInRearDisplayMode) {
- R.raw.biometricprompt_rear_portrait_base
- } else if (isDeviceFolded) {
- R.raw.biometricprompt_folded_base_bottomright
- } else {
- R.raw.biometricprompt_portrait_base_bottomright
- }
- else ->
- if (isInRearDisplayMode) {
- R.raw.biometricprompt_rear_landscape_base
- } else if (isDeviceFolded) {
- R.raw.biometricprompt_folded_base_default
- } else {
- R.raw.biometricprompt_landscape_base
- }
+ isAuthenticated: Boolean,
+ isAuthenticating: Boolean,
+ showingError: Boolean
+ ): Int {
+ return if (isAuthenticated) {
+ if (_previousIconWasError.value) {
+ R.raw.biometricprompt_sfps_error_to_success
+ } else {
+ getSfpsAsset_fingerprintToSuccess(rotation, isInRearDisplayMode)
+ }
+ } else if (isAuthenticating) {
+ if (_previousIconWasError.value) {
+ getSfpsAsset_errorToFingerprint(rotation, isInRearDisplayMode)
+ } else {
+ getSfpsAsset_fingerprintAuthenticating(isInRearDisplayMode)
+ }
+ } else if (showingError) {
+ getSfpsAsset_fingerprintToError(rotation, isInRearDisplayMode)
+ } else {
+ -1
}
+ }
@RawRes
private fun getFaceIconViewAsset(
@@ -272,8 +241,8 @@
isAuthenticating: Boolean,
isPendingConfirmation: Boolean,
showingError: Boolean
- ): Int =
- if (authState.isAuthenticated && isPendingConfirmation) {
+ ): Int {
+ return if (authState.isAuthenticated && isPendingConfirmation) {
R.raw.face_dialog_wink_from_dark
} else if (authState.isAuthenticated) {
R.raw.face_dialog_dark_to_checkmark
@@ -286,6 +255,7 @@
} else {
R.raw.face_dialog_idle_static
}
+ }
@RawRes
private fun getCoexIconViewAsset(
@@ -293,8 +263,8 @@
isAuthenticating: Boolean,
isPendingConfirmation: Boolean,
showingError: Boolean
- ): Int =
- if (authState.isAuthenticatedAndExplicitlyConfirmed) {
+ ): Int {
+ return if (authState.isAuthenticatedAndExplicitlyConfirmed) {
R.raw.fingerprint_dialogue_unlocked_to_checkmark_success_lottie
} else if (isPendingConfirmation) {
if (_previousIconWasError.value) {
@@ -319,107 +289,43 @@
} else {
-1
}
-
- /** Current BiometricPromptLayout.biometric_icon_overlay asset. */
- var iconOverlayAsset: Flow<Int> =
- activeAuthType.flatMapLatest { activeAuthType: AuthType ->
- when (activeAuthType) {
- AuthType.Fingerprint,
- AuthType.Coex ->
- combine(
- displayStateInteractor.currentRotation,
- promptSelectorInteractor.fingerprintSensorType,
- promptViewModel.isAuthenticated,
- promptViewModel.isAuthenticating,
- promptViewModel.showingError
- ) {
- rotation: DisplayRotation,
- sensorType: FingerprintSensorType,
- authState: PromptAuthState,
- isAuthenticating: Boolean,
- showingError: Boolean ->
- when (sensorType) {
- FingerprintSensorType.POWER_BUTTON ->
- getSfpsIconOverlayAsset(
- rotation,
- authState.isAuthenticated,
- isAuthenticating,
- showingError
- )
- else -> -1
- }
- }
- AuthType.Face -> flowOf(-1)
- }
- }
+ }
@RawRes
- private fun getSfpsIconOverlayAsset(
+ private fun getCoexSfpsIconViewAsset(
rotation: DisplayRotation,
- isAuthenticated: Boolean,
+ isInRearDisplayMode: Boolean,
+ authState: PromptAuthState,
isAuthenticating: Boolean,
+ isPendingConfirmation: Boolean,
showingError: Boolean
- ): Int =
- if (isAuthenticated) {
- if (_previousIconOverlayWasError.value) {
- when (rotation) {
- DisplayRotation.ROTATION_0 ->
- R.raw.biometricprompt_symbol_error_to_success_landscape
- DisplayRotation.ROTATION_90 ->
- R.raw.biometricprompt_symbol_error_to_success_portrait_topleft
- DisplayRotation.ROTATION_180 ->
- R.raw.biometricprompt_symbol_error_to_success_landscape
- DisplayRotation.ROTATION_270 ->
- R.raw.biometricprompt_symbol_error_to_success_portrait_bottomright
- }
+ ): Int {
+ return if (authState.isAuthenticatedAndExplicitlyConfirmed) {
+ R.raw.biometricprompt_sfps_unlock_to_success
+ } else if (isPendingConfirmation) {
+ if (_previousIconWasError.value) {
+ R.raw.biometricprompt_sfps_error_to_unlock
} else {
- when (rotation) {
- DisplayRotation.ROTATION_0 ->
- R.raw.biometricprompt_symbol_fingerprint_to_success_landscape
- DisplayRotation.ROTATION_90 ->
- R.raw.biometricprompt_symbol_fingerprint_to_success_portrait_topleft
- DisplayRotation.ROTATION_180 ->
- R.raw.biometricprompt_symbol_fingerprint_to_success_landscape
- DisplayRotation.ROTATION_270 ->
- R.raw.biometricprompt_symbol_fingerprint_to_success_portrait_bottomright
- }
+ getSfpsAsset_fingerprintToUnlock(rotation, isInRearDisplayMode)
+ }
+ } else if (authState.isAuthenticated) {
+ if (_previousIconWasError.value) {
+ R.raw.biometricprompt_sfps_error_to_success
+ } else {
+ getSfpsAsset_fingerprintToSuccess(rotation, isInRearDisplayMode)
}
} else if (isAuthenticating) {
- if (_previousIconOverlayWasError.value) {
- when (rotation) {
- DisplayRotation.ROTATION_0 ->
- R.raw.biometricprompt_symbol_error_to_fingerprint_landscape
- DisplayRotation.ROTATION_90 ->
- R.raw.biometricprompt_symbol_error_to_fingerprint_portrait_topleft
- DisplayRotation.ROTATION_180 ->
- R.raw.biometricprompt_symbol_error_to_fingerprint_landscape
- DisplayRotation.ROTATION_270 ->
- R.raw.biometricprompt_symbol_error_to_fingerprint_portrait_bottomright
- }
+ if (_previousIconWasError.value) {
+ getSfpsAsset_errorToFingerprint(rotation, isInRearDisplayMode)
} else {
- when (rotation) {
- DisplayRotation.ROTATION_0 ->
- R.raw.biometricprompt_fingerprint_to_error_landscape
- DisplayRotation.ROTATION_90 ->
- R.raw.biometricprompt_symbol_fingerprint_to_error_portrait_topleft
- DisplayRotation.ROTATION_180 ->
- R.raw.biometricprompt_fingerprint_to_error_landscape
- DisplayRotation.ROTATION_270 ->
- R.raw.biometricprompt_symbol_fingerprint_to_error_portrait_bottomright
- }
+ getSfpsAsset_fingerprintAuthenticating(isInRearDisplayMode)
}
} else if (showingError) {
- when (rotation) {
- DisplayRotation.ROTATION_0 -> R.raw.biometricprompt_fingerprint_to_error_landscape
- DisplayRotation.ROTATION_90 ->
- R.raw.biometricprompt_symbol_fingerprint_to_error_portrait_topleft
- DisplayRotation.ROTATION_180 -> R.raw.biometricprompt_fingerprint_to_error_landscape
- DisplayRotation.ROTATION_270 ->
- R.raw.biometricprompt_symbol_fingerprint_to_error_portrait_bottomright
- }
+ getSfpsAsset_fingerprintToError(rotation, isInRearDisplayMode)
} else {
-1
}
+ }
/** Content description for iconView */
val contentDescriptionId: Flow<Int> =
@@ -469,7 +375,7 @@
if (isPendingConfirmation) {
when (sensorType) {
FingerprintSensorType.POWER_BUTTON -> -1
- else -> R.string.fingerprint_dialog_authenticated_confirmation
+ else -> R.string.biometric_dialog_confirm
}
} else if (isAuthenticating || isAuthenticated) {
when (sensorType) {
@@ -516,12 +422,7 @@
isAuthenticating: Boolean,
showingError: Boolean ->
when (sensorType) {
- FingerprintSensorType.POWER_BUTTON ->
- shouldAnimateSfpsIconView(
- authState.isAuthenticated,
- isAuthenticating,
- showingError
- )
+ FingerprintSensorType.POWER_BUTTON -> true
else ->
shouldAnimateFingerprintIconView(
authState.isAuthenticated,
@@ -556,12 +457,7 @@
isPendingConfirmation: Boolean,
showingError: Boolean ->
when (sensorType) {
- FingerprintSensorType.POWER_BUTTON ->
- shouldAnimateSfpsIconView(
- authState.isAuthenticated,
- isAuthenticating,
- showingError
- )
+ FingerprintSensorType.POWER_BUTTON -> true
else ->
shouldAnimateCoexIconView(
authState.isAuthenticated,
@@ -574,18 +470,22 @@
}
}
+ /** Whether the current BiometricPromptLayout.iconView asset animation should be looping. */
+ val shouldLoopIconView: Flow<Boolean> =
+ activeAuthType.flatMapLatest { activeAuthType: AuthType ->
+ when (activeAuthType) {
+ AuthType.Fingerprint,
+ AuthType.Coex -> flowOf(false)
+ AuthType.Face -> promptViewModel.isAuthenticating
+ }
+ }
+
private fun shouldAnimateFingerprintIconView(
isAuthenticated: Boolean,
isAuthenticating: Boolean,
showingError: Boolean
) = (isAuthenticating && _previousIconWasError.value) || isAuthenticated || showingError
- private fun shouldAnimateSfpsIconView(
- isAuthenticated: Boolean,
- isAuthenticating: Boolean,
- showingError: Boolean
- ) = isAuthenticated || isAuthenticating || showingError
-
private fun shouldAnimateCoexIconView(
isAuthenticated: Boolean,
isAuthenticating: Boolean,
@@ -597,89 +497,123 @@
isAuthenticated ||
showingError
- /** Whether the current iconOverlayAsset animation should be playing. */
- val shouldAnimateIconOverlay: Flow<Boolean> =
- activeAuthType.flatMapLatest { activeAuthType: AuthType ->
- when (activeAuthType) {
- AuthType.Fingerprint,
- AuthType.Coex ->
- combine(
- promptSelectorInteractor.fingerprintSensorType,
- promptViewModel.isAuthenticated,
- promptViewModel.isAuthenticating,
- promptViewModel.showingError
- ) {
- sensorType: FingerprintSensorType,
- authState: PromptAuthState,
- isAuthenticating: Boolean,
- showingError: Boolean ->
- when (sensorType) {
- FingerprintSensorType.POWER_BUTTON ->
- shouldAnimateSfpsIconOverlay(
- authState.isAuthenticated,
- isAuthenticating,
- showingError
- )
- else -> false
- }
- }
- AuthType.Face -> flowOf(false)
+ /* Used to rotate the iconView for assets reused across rotations. */
+ val iconViewRotation: Flow<Float> =
+ combine(iconAsset, displayStateInteractor.currentRotation) {
+ icon: Int,
+ rotation: DisplayRotation ->
+ if (assetReusedAcrossRotations(icon)) {
+ when (rotation) {
+ DisplayRotation.ROTATION_0 -> 0f
+ DisplayRotation.ROTATION_90 -> 270f
+ DisplayRotation.ROTATION_180 -> 180f
+ DisplayRotation.ROTATION_270 -> 90f
+ }
+ } else {
+ 0f
}
}
- private fun shouldAnimateSfpsIconOverlay(
- isAuthenticated: Boolean,
- isAuthenticating: Boolean,
- showingError: Boolean
- ) = (isAuthenticating && _previousIconOverlayWasError.value) || isAuthenticated || showingError
+ private fun assetReusedAcrossRotations(asset: Int): Boolean {
+ return asset in assetsReusedAcrossRotations
+ }
- /** Whether the iconView should be flipped due to a device using reverse default rotation . */
- val shouldFlipIconView: Flow<Boolean> =
- activeAuthType.flatMapLatest { activeAuthType: AuthType ->
- when (activeAuthType) {
- AuthType.Fingerprint,
- AuthType.Coex ->
- combine(
- promptSelectorInteractor.fingerprintSensorType,
- displayStateInteractor.currentRotation
- ) { sensorType: FingerprintSensorType, rotation: DisplayRotation ->
- when (sensorType) {
- FingerprintSensorType.POWER_BUTTON ->
- (rotation == DisplayRotation.ROTATION_180)
- else -> false
- }
- }
- AuthType.Face -> flowOf(false)
- }
- }
+ private val assetsReusedAcrossRotations: List<Int> =
+ listOf(
+ R.raw.biometricprompt_sfps_fingerprint_authenticating,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_authenticating,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_authenticating
+ )
/** Called on configuration changes */
fun onConfigurationChanged(newConfig: Configuration) {
displayStateInteractor.onConfigurationChanged(newConfig)
}
- /** iconView assets for caching */
- fun getRawAssets(hasSfps: Boolean): List<Int> {
- return if (hasSfps) {
+ /** Coex iconView assets for caching */
+ fun getCoexAssetsList(hasSfps: Boolean): List<Int> =
+ if (hasSfps) {
listOf(
- R.raw.biometricprompt_fingerprint_to_error_landscape,
- R.raw.biometricprompt_folded_base_bottomright,
- R.raw.biometricprompt_folded_base_default,
- R.raw.biometricprompt_folded_base_topleft,
- R.raw.biometricprompt_landscape_base,
- R.raw.biometricprompt_portrait_base_bottomright,
- R.raw.biometricprompt_portrait_base_topleft,
- R.raw.biometricprompt_symbol_error_to_fingerprint_landscape,
- R.raw.biometricprompt_symbol_error_to_fingerprint_portrait_bottomright,
- R.raw.biometricprompt_symbol_error_to_fingerprint_portrait_topleft,
- R.raw.biometricprompt_symbol_error_to_success_landscape,
- R.raw.biometricprompt_symbol_error_to_success_portrait_bottomright,
- R.raw.biometricprompt_symbol_error_to_success_portrait_topleft,
- R.raw.biometricprompt_symbol_fingerprint_to_error_portrait_bottomright,
- R.raw.biometricprompt_symbol_fingerprint_to_error_portrait_topleft,
- R.raw.biometricprompt_symbol_fingerprint_to_success_landscape,
- R.raw.biometricprompt_symbol_fingerprint_to_success_portrait_bottomright,
- R.raw.biometricprompt_symbol_fingerprint_to_success_portrait_topleft
+ R.raw.biometricprompt_sfps_fingerprint_authenticating,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_authenticating,
+ R.raw.biometricprompt_sfps_error_to_unlock,
+ R.raw.biometricprompt_sfps_error_to_success,
+ R.raw.biometricprompt_sfps_fingerprint_to_error,
+ R.raw.biometricprompt_sfps_fingerprint_to_error_90,
+ R.raw.biometricprompt_sfps_fingerprint_to_error_180,
+ R.raw.biometricprompt_sfps_fingerprint_to_error_270,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_error,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_error_90,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_error_180,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_error_270,
+ R.raw.biometricprompt_sfps_error_to_fingerprint,
+ R.raw.biometricprompt_sfps_error_to_fingerprint_90,
+ R.raw.biometricprompt_sfps_error_to_fingerprint_180,
+ R.raw.biometricprompt_sfps_error_to_fingerprint_270,
+ R.raw.biometricprompt_sfps_rear_display_error_to_fingerprint,
+ R.raw.biometricprompt_sfps_rear_display_error_to_fingerprint_90,
+ R.raw.biometricprompt_sfps_rear_display_error_to_fingerprint_180,
+ R.raw.biometricprompt_sfps_rear_display_error_to_fingerprint_270,
+ R.raw.biometricprompt_sfps_fingerprint_to_unlock,
+ R.raw.biometricprompt_sfps_fingerprint_to_unlock_90,
+ R.raw.biometricprompt_sfps_fingerprint_to_unlock_180,
+ R.raw.biometricprompt_sfps_fingerprint_to_unlock_270,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_unlock,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_unlock_90,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_unlock_180,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_unlock_270,
+ R.raw.biometricprompt_sfps_fingerprint_to_success,
+ R.raw.biometricprompt_sfps_fingerprint_to_success_90,
+ R.raw.biometricprompt_sfps_fingerprint_to_success_180,
+ R.raw.biometricprompt_sfps_fingerprint_to_success_270,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_success,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_success_90,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_success_180,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_success_270,
+ )
+ } else {
+ listOf(
+ R.raw.fingerprint_dialogue_unlocked_to_checkmark_success_lottie,
+ R.raw.fingerprint_dialogue_error_to_unlock_lottie,
+ R.raw.fingerprint_dialogue_fingerprint_to_unlock_lottie,
+ R.raw.fingerprint_dialogue_error_to_success_lottie,
+ R.raw.fingerprint_dialogue_fingerprint_to_success_lottie,
+ R.raw.fingerprint_dialogue_error_to_fingerprint_lottie,
+ R.raw.fingerprint_dialogue_fingerprint_to_error_lottie
+ )
+ }
+
+ /** Fingerprint iconView assets for caching */
+ fun getFingerprintAssetsList(hasSfps: Boolean): List<Int> =
+ if (hasSfps) {
+ listOf(
+ R.raw.biometricprompt_sfps_fingerprint_authenticating,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_authenticating,
+ R.raw.biometricprompt_sfps_error_to_success,
+ R.raw.biometricprompt_sfps_fingerprint_to_error,
+ R.raw.biometricprompt_sfps_fingerprint_to_error_90,
+ R.raw.biometricprompt_sfps_fingerprint_to_error_180,
+ R.raw.biometricprompt_sfps_fingerprint_to_error_270,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_error,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_error_90,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_error_180,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_error_270,
+ R.raw.biometricprompt_sfps_error_to_fingerprint,
+ R.raw.biometricprompt_sfps_error_to_fingerprint_90,
+ R.raw.biometricprompt_sfps_error_to_fingerprint_180,
+ R.raw.biometricprompt_sfps_error_to_fingerprint_270,
+ R.raw.biometricprompt_sfps_rear_display_error_to_fingerprint,
+ R.raw.biometricprompt_sfps_rear_display_error_to_fingerprint_90,
+ R.raw.biometricprompt_sfps_rear_display_error_to_fingerprint_180,
+ R.raw.biometricprompt_sfps_rear_display_error_to_fingerprint_270,
+ R.raw.biometricprompt_sfps_fingerprint_to_success,
+ R.raw.biometricprompt_sfps_fingerprint_to_success_90,
+ R.raw.biometricprompt_sfps_fingerprint_to_success_180,
+ R.raw.biometricprompt_sfps_fingerprint_to_success_270,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_success,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_success_90,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_success_180,
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_success_270,
)
} else {
listOf(
@@ -689,5 +623,120 @@
R.raw.fingerprint_dialogue_fingerprint_to_success_lottie
)
}
- }
+
+ /** Face iconView assets for caching */
+ fun getFaceAssetsList(): List<Int> =
+ listOf(
+ R.raw.face_dialog_wink_from_dark,
+ R.raw.face_dialog_dark_to_checkmark,
+ R.raw.face_dialog_dark_to_error,
+ R.raw.face_dialog_error_to_idle,
+ R.raw.face_dialog_idle_static,
+ R.raw.face_dialog_authenticating
+ )
+
+ private fun getSfpsAsset_fingerprintAuthenticating(isInRearDisplayMode: Boolean): Int =
+ if (isInRearDisplayMode) {
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_authenticating
+ } else {
+ R.raw.biometricprompt_sfps_fingerprint_authenticating
+ }
+
+ private fun getSfpsAsset_fingerprintToError(
+ rotation: DisplayRotation,
+ isInRearDisplayMode: Boolean
+ ): Int =
+ if (isInRearDisplayMode) {
+ when (rotation) {
+ DisplayRotation.ROTATION_0 ->
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_error
+ DisplayRotation.ROTATION_90 ->
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_error_90
+ DisplayRotation.ROTATION_180 ->
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_error_180
+ DisplayRotation.ROTATION_270 ->
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_error_270
+ }
+ } else {
+ when (rotation) {
+ DisplayRotation.ROTATION_0 -> R.raw.biometricprompt_sfps_fingerprint_to_error
+ DisplayRotation.ROTATION_90 -> R.raw.biometricprompt_sfps_fingerprint_to_error_90
+ DisplayRotation.ROTATION_180 -> R.raw.biometricprompt_sfps_fingerprint_to_error_180
+ DisplayRotation.ROTATION_270 -> R.raw.biometricprompt_sfps_fingerprint_to_error_270
+ }
+ }
+
+ private fun getSfpsAsset_errorToFingerprint(
+ rotation: DisplayRotation,
+ isInRearDisplayMode: Boolean
+ ): Int =
+ if (isInRearDisplayMode) {
+ when (rotation) {
+ DisplayRotation.ROTATION_0 ->
+ R.raw.biometricprompt_sfps_rear_display_error_to_fingerprint
+ DisplayRotation.ROTATION_90 ->
+ R.raw.biometricprompt_sfps_rear_display_error_to_fingerprint_90
+ DisplayRotation.ROTATION_180 ->
+ R.raw.biometricprompt_sfps_rear_display_error_to_fingerprint_180
+ DisplayRotation.ROTATION_270 ->
+ R.raw.biometricprompt_sfps_rear_display_error_to_fingerprint_270
+ }
+ } else {
+ when (rotation) {
+ DisplayRotation.ROTATION_0 -> R.raw.biometricprompt_sfps_error_to_fingerprint
+ DisplayRotation.ROTATION_90 -> R.raw.biometricprompt_sfps_error_to_fingerprint_90
+ DisplayRotation.ROTATION_180 -> R.raw.biometricprompt_sfps_error_to_fingerprint_180
+ DisplayRotation.ROTATION_270 -> R.raw.biometricprompt_sfps_error_to_fingerprint_270
+ }
+ }
+
+ private fun getSfpsAsset_fingerprintToUnlock(
+ rotation: DisplayRotation,
+ isInRearDisplayMode: Boolean
+ ): Int =
+ if (isInRearDisplayMode) {
+ when (rotation) {
+ DisplayRotation.ROTATION_0 ->
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_unlock
+ DisplayRotation.ROTATION_90 ->
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_unlock_90
+ DisplayRotation.ROTATION_180 ->
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_unlock_180
+ DisplayRotation.ROTATION_270 ->
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_unlock_270
+ }
+ } else {
+ when (rotation) {
+ DisplayRotation.ROTATION_0 -> R.raw.biometricprompt_sfps_fingerprint_to_unlock
+ DisplayRotation.ROTATION_90 -> R.raw.biometricprompt_sfps_fingerprint_to_unlock_90
+ DisplayRotation.ROTATION_180 -> R.raw.biometricprompt_sfps_fingerprint_to_unlock_180
+ DisplayRotation.ROTATION_270 -> R.raw.biometricprompt_sfps_fingerprint_to_unlock_270
+ }
+ }
+
+ private fun getSfpsAsset_fingerprintToSuccess(
+ rotation: DisplayRotation,
+ isInRearDisplayMode: Boolean
+ ): Int =
+ if (isInRearDisplayMode) {
+ when (rotation) {
+ DisplayRotation.ROTATION_0 ->
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_success
+ DisplayRotation.ROTATION_90 ->
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_success_90
+ DisplayRotation.ROTATION_180 ->
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_success_180
+ DisplayRotation.ROTATION_270 ->
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_success_270
+ }
+ } else {
+ when (rotation) {
+ DisplayRotation.ROTATION_0 -> R.raw.biometricprompt_sfps_fingerprint_to_success
+ DisplayRotation.ROTATION_90 -> R.raw.biometricprompt_sfps_fingerprint_to_success_90
+ DisplayRotation.ROTATION_180 ->
+ R.raw.biometricprompt_sfps_fingerprint_to_success_180
+ DisplayRotation.ROTATION_270 ->
+ R.raw.biometricprompt_sfps_fingerprint_to_success_270
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
index b1cba2f..fbc6470 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
@@ -36,7 +36,6 @@
import android.view.HapticFeedbackConstants
import android.view.MotionEvent
import com.android.launcher3.icons.IconProvider
-import com.android.systemui.Flags.bpTalkback
import com.android.systemui.Flags.constraintBp
import com.android.systemui.biometrics.UdfpsUtils
import com.android.systemui.biometrics.Utils
@@ -410,12 +409,7 @@
.distinctUntilChanged()
val iconViewModel: PromptIconViewModel =
- PromptIconViewModel(
- this,
- displayStateInteractor,
- promptSelectorInteractor,
- udfpsOverlayInteractor
- )
+ PromptIconViewModel(this, displayStateInteractor, promptSelectorInteractor)
private val _isIconViewLoaded = MutableStateFlow(false)
@@ -471,26 +465,13 @@
}
}
- /** Logo for the prompt. */
- val logo: Flow<Drawable?> =
+ /** (logoIcon, logoDescription) for the prompt. */
+ val logoInfo: Flow<Pair<Drawable?, String>> =
promptSelectorInteractor.prompt
.map {
when {
- !(customBiometricPrompt() && constraintBp()) || it == null -> null
- it.logoBitmap != null -> BitmapDrawable(context.resources, it.logoBitmap)
- else -> context.getUserBadgedIcon(it, iconProvider, activityTaskManager)
- }
- }
- .distinctUntilChanged()
-
- /** Logo description for the prompt. */
- val logoDescription: Flow<String> =
- promptSelectorInteractor.prompt
- .map {
- when {
- !(customBiometricPrompt() && constraintBp()) || it == null -> ""
- !it.logoDescription.isNullOrEmpty() -> it.logoDescription
- else -> context.getUserBadgedLabel(it, activityTaskManager)
+ !(customBiometricPrompt() && constraintBp()) || it == null -> Pair(null, "")
+ else -> context.getUserBadgedLogoInfo(it, iconProvider, activityTaskManager)
}
}
.distinctUntilChanged()
@@ -916,8 +897,7 @@
touchExplorationEnabled: Boolean,
): Boolean {
if (
- bpTalkback() &&
- modalities.first().hasUdfps &&
+ modalities.first().hasUdfps &&
touchExplorationEnabled &&
!isAuthenticated.first().isAuthenticated
) {
@@ -987,43 +967,60 @@
}
}
-private fun Context.getUserBadgedIcon(
+/**
+ * The order of getting logo icon/description is:
+ * 1. If the app sets customized icon/description, use the passed-in value
+ * 2. If shouldShowLogoWithOverrides(), use activityInfo to get icon/description
+ * 3. Otherwise, use applicationInfo to get icon/description
+ */
+private fun Context.getUserBadgedLogoInfo(
prompt: BiometricPromptRequest.Biometric,
iconProvider: IconProvider,
activityTaskManager: ActivityTaskManager
-): Drawable? {
- var icon: Drawable? = null
- val componentName = prompt.getComponentNameForLogo(activityTaskManager)
- if (componentName != null && shouldShowLogoWithOverrides(componentName)) {
- val activityInfo = getActivityInfo(componentName)
- icon = if (activityInfo == null) null else iconProvider.getIcon(activityInfo)
+): Pair<Drawable?, String> {
+ var icon: Drawable? =
+ if (prompt.logoBitmap != null) BitmapDrawable(resources, prompt.logoBitmap) else null
+ var label = prompt.logoDescription ?: ""
+ if (icon != null && label.isNotEmpty()) {
+ return Pair(icon, label)
}
- if (icon == null) {
- val appInfo = prompt.getApplicationInfoForLogo(this, componentName)
- if (appInfo == null) {
- Log.w(PromptViewModel.TAG, "Cannot find app logo for package $opPackageName")
- return null
- } else {
- icon = packageManager.getApplicationIcon(appInfo)
+
+ // Use activityInfo if shouldUseActivityLogo() is true
+ val componentName = prompt.getComponentNameForLogo(activityTaskManager)
+ if (componentName != null && shouldUseActivityLogo(componentName)) {
+ val activityInfo = getActivityInfo(componentName)
+ if (activityInfo != null) {
+ if (icon == null) {
+ icon = iconProvider.getIcon(activityInfo)
+ }
+ if (label.isEmpty()) {
+ label = activityInfo.loadLabel(packageManager).toString()
+ }
}
}
- return packageManager.getUserBadgedIcon(icon, UserHandle.of(prompt.userInfo.userId))
-}
-
-private fun Context.getUserBadgedLabel(
- prompt: BiometricPromptRequest.Biometric,
- activityTaskManager: ActivityTaskManager
-): String {
- val componentName = prompt.getComponentNameForLogo(activityTaskManager)
- val appInfo = prompt.getApplicationInfoForLogo(this, componentName)
- return if (appInfo == null || packageManager.getApplicationLabel(appInfo).isNullOrEmpty()) {
- Log.w(PromptViewModel.TAG, "Cannot find app logo for package $opPackageName")
- ""
- } else {
- packageManager
- .getUserBadgedLabel(packageManager.getApplicationLabel(appInfo), UserHandle.of(userId))
- .toString()
+ if (icon != null && label.isNotEmpty()) {
+ return Pair(icon, label)
}
+
+ // Use applicationInfo for other cases
+ val appInfo = prompt.getApplicationInfo(this, componentName)
+ if (appInfo == null) {
+ Log.w(PromptViewModel.TAG, "Cannot find app logo for package $opPackageName")
+ } else {
+ if (icon == null) {
+ icon = packageManager.getApplicationIcon(appInfo)
+ }
+ if (label.isEmpty()) {
+ label =
+ packageManager
+ .getUserBadgedLabel(
+ packageManager.getApplicationLabel(appInfo),
+ UserHandle.of(userId)
+ )
+ .toString()
+ }
+ }
+ return Pair(icon, label)
}
private fun BiometricPromptRequest.Biometric.getComponentNameForLogo(
@@ -1041,7 +1038,7 @@
}
}
-private fun BiometricPromptRequest.Biometric.getApplicationInfoForLogo(
+private fun BiometricPromptRequest.Biometric.getApplicationInfo(
context: Context,
componentNameForLogo: ComponentName?
): ApplicationInfo? {
@@ -1058,14 +1055,22 @@
Log.w(PromptViewModel.TAG, "Cannot find application info for $opPackageName")
null
} else {
- context.getApplicationInfo(packageName)
+ try {
+ context.packageManager.getApplicationInfo(
+ packageName,
+ PackageManager.MATCH_DISABLED_COMPONENTS or PackageManager.MATCH_ANY_USER
+ )
+ } catch (e: PackageManager.NameNotFoundException) {
+ Log.w(PromptViewModel.TAG, "Cannot find application info for $opPackageName", e)
+ null
+ }
}
}
-private fun Context.shouldShowLogoWithOverrides(componentName: ComponentName): Boolean {
- return resources
- .getStringArray(R.array.biometric_dialog_package_names_for_logo_with_overrides)
- .find { componentName.packageName.contentEquals(it) } != null
+private fun Context.shouldUseActivityLogo(componentName: ComponentName): Boolean {
+ return resources.getStringArray(R.array.config_useActivityLogoForBiometricPrompt).find {
+ componentName.packageName.contentEquals(it)
+ } != null
}
private fun Context.getActivityInfo(componentName: ComponentName): ActivityInfo? =
@@ -1076,17 +1081,6 @@
null
}
-private fun Context.getApplicationInfo(packageName: String): ApplicationInfo? =
- try {
- packageManager.getApplicationInfo(
- packageName,
- PackageManager.MATCH_DISABLED_COMPONENTS or PackageManager.MATCH_ANY_USER
- )
- } catch (e: PackageManager.NameNotFoundException) {
- Log.w(PromptViewModel.TAG, "Cannot find application info for $opPackageName", e)
- null
- }
-
/** How the fingerprint sensor was started for the prompt. */
enum class FingerprintStartMode {
/** Fingerprint sensor has not started. */
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt
index 4984fc6..373671d0 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt
@@ -21,7 +21,7 @@
import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFingerprintAuthInteractor
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryBiometricsAllowedInteractor
import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
@@ -60,7 +60,8 @@
private val biometricSettingsRepository: BiometricSettingsRepository,
private val systemClock: SystemClock,
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
- private val deviceEntryFingerprintAuthInteractor: Lazy<DeviceEntryFingerprintAuthInteractor>,
+ private val deviceEntryBiometricsAllowedInteractor:
+ Lazy<DeviceEntryBiometricsAllowedInteractor>,
private val keyguardInteractor: Lazy<KeyguardInteractor>,
keyguardTransitionInteractor: Lazy<KeyguardTransitionInteractor>,
sceneInteractor: Lazy<SceneInteractor>,
@@ -114,7 +115,7 @@
flowOf(false)
} else {
combine(
- deviceEntryFingerprintAuthInteractor
+ deviceEntryBiometricsAllowedInteractor
.get()
.isFingerprintAuthCurrentlyAllowed,
keyguardInteractor.get().isKeyguardDismissible,
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt
index 35015e7..8e12646 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt
@@ -33,6 +33,7 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.deviceentry.data.repository.DeviceEntryFaceAuthRepository
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryBiometricsAllowedInteractor
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFingerprintAuthInteractor
import com.android.systemui.flags.SystemPropertiesHelper
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
@@ -76,10 +77,11 @@
private val deviceEntryFingerprintAuthInteractor: DeviceEntryFingerprintAuthInteractor,
faceAuthRepository: DeviceEntryFaceAuthRepository,
private val securityModel: KeyguardSecurityModel,
+ deviceEntryBiometricsAllowedInteractor: DeviceEntryBiometricsAllowedInteractor,
) {
private val isFingerprintAuthCurrentlyAllowedOnBouncer =
- deviceEntryFingerprintAuthInteractor.isFingerprintCurrentlyAllowedOnBouncer.stateIn(
+ deviceEntryBiometricsAllowedInteractor.isFingerprintCurrentlyAllowedOnBouncer.stateIn(
applicationScope,
SharingStarted.Eagerly,
false
@@ -87,6 +89,7 @@
private val currentSecurityMode
get() = securityModel.getSecurityMode(currentUserId)
+
private val currentUserId
get() = userRepository.getSelectedUserInfo().id
@@ -349,6 +352,7 @@
interface CountDownTimerCallback {
fun onFinish()
+
fun onTick(millisUntilFinished: Long)
}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/log/BouncerLoggerStartable.kt b/packages/SystemUI/src/com/android/systemui/bouncer/log/BouncerLoggerStartable.kt
index 29c4f2e..87ec254 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/log/BouncerLoggerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/log/BouncerLoggerStartable.kt
@@ -20,6 +20,7 @@
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryBiometricSettingsInteractor
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryBiometricsAllowedInteractor
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFingerprintAuthInteractor
import com.android.systemui.log.BouncerLogger
@@ -39,6 +40,7 @@
private val faceAuthInteractor: DeviceEntryFaceAuthInteractor,
private val fingerprintAuthInteractor: DeviceEntryFingerprintAuthInteractor,
private val bouncerLogger: BouncerLogger,
+ private val deviceEntryBiometricsAllowedInteractor: DeviceEntryBiometricsAllowedInteractor,
) : CoreStartable {
override fun start() {
if (!Build.isDebuggable()) {
@@ -69,13 +71,13 @@
}
}
applicationScope.launch {
- fingerprintAuthInteractor.isFingerprintCurrentlyAllowedOnBouncer.collectLatest {
- newValue ->
- bouncerLogger.interestedStateChanged(
- "fingerprintCurrentlyAllowedOnBouncer",
- newValue
- )
- }
+ deviceEntryBiometricsAllowedInteractor.isFingerprintCurrentlyAllowedOnBouncer
+ .collectLatest { newValue ->
+ bouncerLogger.interestedStateChanged(
+ "fingerprintCurrentlyAllowedOnBouncer",
+ newValue
+ )
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt
index 810b6d1..31479f1 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt
@@ -30,8 +30,8 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.deviceentry.domain.interactor.BiometricMessageInteractor
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryBiometricsAllowedInteractor
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFingerprintAuthInteractor
import com.android.systemui.deviceentry.domain.interactor.DeviceUnlockedInteractor
import com.android.systemui.deviceentry.shared.model.DeviceEntryRestrictionReason
import com.android.systemui.deviceentry.shared.model.FaceFailureMessage
@@ -76,7 +76,7 @@
private val biometricMessageInteractor: BiometricMessageInteractor,
private val faceAuthInteractor: DeviceEntryFaceAuthInteractor,
private val deviceUnlockedInteractor: DeviceUnlockedInteractor,
- private val fingerprintInteractor: DeviceEntryFingerprintAuthInteractor,
+ private val deviceEntryBiometricsAllowedInteractor: DeviceEntryBiometricsAllowedInteractor,
flags: ComposeBouncerFlags,
) {
/**
@@ -121,7 +121,8 @@
combine(
deviceUnlockedInteractor.deviceEntryRestrictionReason,
lockoutMessage,
- fingerprintInteractor.isFingerprintCurrentlyAllowedOnBouncer,
+ deviceEntryBiometricsAllowedInteractor
+ .isFingerprintCurrentlyAllowedOnBouncer,
resetToDefault,
) { deviceEntryRestrictedReason, lockoutMsg, isFpAllowedInBouncer, _ ->
lockoutMsg
@@ -168,7 +169,7 @@
biometricMessageInteractor.faceMessage
.sample(
authenticationInteractor.authenticationMethod,
- fingerprintInteractor.isFingerprintCurrentlyAllowedOnBouncer,
+ deviceEntryBiometricsAllowedInteractor.isFingerprintCurrentlyAllowedOnBouncer,
)
.collectLatest { (faceMessage, authMethod, fingerprintAllowedOnBouncer) ->
val isFaceAuthStrong = faceAuthInteractor.isFaceAuthStrong()
@@ -223,7 +224,7 @@
biometricMessageInteractor.fingerprintMessage
.sample(
authenticationInteractor.authenticationMethod,
- fingerprintInteractor.isFingerprintCurrentlyAllowedOnBouncer
+ deviceEntryBiometricsAllowedInteractor.isFingerprintCurrentlyAllowedOnBouncer
)
.collectLatest { (fingerprintMessage, authMethod, isFingerprintAllowed) ->
val defaultPrimaryMessage =
@@ -261,7 +262,7 @@
bouncerInteractor.onIncorrectBouncerInput
.sample(
authenticationInteractor.authenticationMethod,
- fingerprintInteractor.isFingerprintCurrentlyAllowedOnBouncer
+ deviceEntryBiometricsAllowedInteractor.isFingerprintCurrentlyAllowedOnBouncer
)
.collectLatest { (_, authMethod, isFingerprintAllowed) ->
message.emit(
@@ -414,7 +415,7 @@
biometricMessageInteractor: BiometricMessageInteractor,
faceAuthInteractor: DeviceEntryFaceAuthInteractor,
deviceUnlockedInteractor: DeviceUnlockedInteractor,
- fingerprintInteractor: DeviceEntryFingerprintAuthInteractor,
+ deviceEntryBiometricsAllowedInteractor: DeviceEntryBiometricsAllowedInteractor,
flags: ComposeBouncerFlags,
userSwitcherViewModel: UserSwitcherViewModel,
): BouncerMessageViewModel {
@@ -428,7 +429,7 @@
biometricMessageInteractor = biometricMessageInteractor,
faceAuthInteractor = faceAuthInteractor,
deviceUnlockedInteractor = deviceUnlockedInteractor,
- fingerprintInteractor = fingerprintInteractor,
+ deviceEntryBiometricsAllowedInteractor = deviceEntryBiometricsAllowedInteractor,
flags = flags,
selectedUser = userSwitcherViewModel.selectedUser,
)
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayWindow.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayWindow.java
index 9dac9b3..0dc6fda 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayWindow.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayWindow.java
@@ -18,10 +18,8 @@
import android.annotation.MainThread;
import android.annotation.NonNull;
-import android.app.ICompatCameraControlCallback;
import android.content.Context;
import android.content.res.Configuration;
-import android.util.Log;
import android.view.View;
import android.view.ViewRootImpl;
import android.view.ViewTreeObserver;
@@ -104,12 +102,6 @@
}
}
- @Override // ViewRootImpl.ActivityConfigCallback
- public void requestCompatCameraControl(boolean showControl, boolean transformationApplied,
- ICompatCameraControlCallback callback) {
- Log.w(TAG, "unexpected requestCompatCameraControl call");
- }
-
void remove() {
final View decorView = peekDecorView();
if (decorView != null && decorView.isAttachedToWindow()) {
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 64dedea..108e22b 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
@@ -16,7 +16,6 @@
package com.android.systemui.common.ui.binder
-import android.view.View
import android.widget.ImageView
import com.android.systemui.common.shared.model.Icon
@@ -31,13 +30,4 @@
is Icon.Resource -> view.setImageResource(icon.res)
}
}
-
- fun bindNullable(icon: Icon?, view: ImageView) {
- if (icon != null) {
- view.visibility = View.VISIBLE
- bind(icon, view)
- } else {
- view.visibility = View.GONE
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractor.kt
index 6a20610..c780aac 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractor.kt
@@ -175,7 +175,7 @@
}
}
- private fun finishCurrentTransition() {
+ private suspend fun finishCurrentTransition() {
internalTransitionInteractor.updateTransition(
currentTransitionId!!,
1f,
@@ -285,7 +285,7 @@
currentTransitionId = internalTransitionInteractor.startTransition(transitionInfo)
}
- private fun updateProgress(progress: Float) {
+ private suspend fun updateProgress(progress: Float) {
if (currentTransitionId == null) return
internalTransitionInteractor.updateTransition(
currentTransitionId!!,
diff --git a/packages/SystemUI/src/com/android/systemui/communal/smartspace/SmartspaceInteractionHandler.kt b/packages/SystemUI/src/com/android/systemui/communal/smartspace/SmartspaceInteractionHandler.kt
index 4e3d3ff..c4edcac 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/smartspace/SmartspaceInteractionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/smartspace/SmartspaceInteractionHandler.kt
@@ -25,6 +25,9 @@
import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor
import com.android.systemui.communal.util.InteractionHandlerDelegate
import com.android.systemui.communal.widgets.SmartspaceAppWidgetHostView
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.Logger
+import com.android.systemui.log.dagger.CommunalLog
import com.android.systemui.plugins.ActivityStarter
import javax.inject.Inject
@@ -34,12 +37,19 @@
constructor(
private val activityStarter: ActivityStarter,
communalSceneInteractor: CommunalSceneInteractor,
+ @CommunalLog val logBuffer: LogBuffer,
) : RemoteViews.InteractionHandler {
+
+ private companion object {
+ const val TAG = "SmartspaceInteractionHandler"
+ }
+
private val delegate =
InteractionHandlerDelegate(
communalSceneInteractor,
findViewToAnimate = { view -> view is SmartspaceAppWidgetHostView },
intentStarter = this::startIntent,
+ logger = Logger(logBuffer, TAG),
)
override fun onInteraction(
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
index 3fc8b09..b06cf3f 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
@@ -97,8 +97,10 @@
private val metricsLogger: CommunalMetricsLogger,
) : BaseCommunalViewModel(communalSceneInteractor, communalInteractor, mediaHost) {
+ private val logger = Logger(logBuffer, "CommunalViewModel")
+
private val _isMediaHostVisible =
- conflatedCallbackFlow<Boolean> {
+ conflatedCallbackFlow {
val callback = { visible: Boolean ->
trySend(visible)
Unit
@@ -106,11 +108,18 @@
mediaHost.addVisibilityChangeListener(callback)
awaitClose { mediaHost.removeVisibilityChangeListener(callback) }
}
- .onStart { emit(mediaHost.visible) }
+ .onStart {
+ // Ensure the visibility state is correct when the hub is opened and this flow is
+ // started so that the UMO is shown when needed. The visibility state in MediaHost
+ // is not updated once its view has been detached, aka the hub is closed, which can
+ // result in this getting stuck as False and never being updated as the UMO is not
+ // shown.
+ mediaHost.updateViewVisibility()
+ emit(mediaHost.visible)
+ }
+ .onEach { logger.d({ "_isMediaHostVisible: $bool1" }) { bool1 = it } }
.flowOn(mainDispatcher)
- private val logger = Logger(logBuffer, "CommunalViewModel")
-
/** Communal content saved from the previous emission when the flow is active (not "frozen"). */
private var frozenCommunalContent: List<CommunalContentModel>? = null
diff --git a/packages/SystemUI/src/com/android/systemui/communal/util/InteractionHandlerDelegate.kt b/packages/SystemUI/src/com/android/systemui/communal/util/InteractionHandlerDelegate.kt
index 51a5fcd..d2029d5 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/util/InteractionHandlerDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/util/InteractionHandlerDelegate.kt
@@ -26,12 +26,14 @@
import com.android.systemui.animation.ActivityTransitionAnimator
import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor
import com.android.systemui.communal.widgets.CommunalTransitionAnimatorController
+import com.android.systemui.log.core.Logger
/** A delegate that can be used to launch activities from [RemoteViews] */
class InteractionHandlerDelegate(
private val communalSceneInteractor: CommunalSceneInteractor,
private val findViewToAnimate: (View) -> Boolean,
private val intentStarter: IntentStarter,
+ private val logger: Logger,
) : RemoteViews.InteractionHandler {
/** Responsible for starting the pending intent for launching activities. */
@@ -49,6 +51,10 @@
pendingIntent: PendingIntent,
response: RemoteViews.RemoteResponse
): Boolean {
+ logger.i({ "Starting $str1 ($str2)" }) {
+ str1 = pendingIntent.toLoggingString()
+ str2 = pendingIntent.creatorPackage
+ }
val launchOptions = response.getLaunchOptions(view)
return when {
pendingIntent.isActivity -> {
@@ -82,3 +88,12 @@
return null
}
}
+
+private fun PendingIntent.toLoggingString() =
+ when {
+ isActivity -> "activity"
+ isBroadcast -> "broadcast"
+ isForegroundService -> "fgService"
+ isService -> "service"
+ else -> "unknown"
+ }
diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHost.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHost.kt
index 058ca4d..10a565f 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHost.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHost.kt
@@ -36,7 +36,7 @@
context: Context,
private val backgroundScope: CoroutineScope,
hostId: Int,
- interactionHandler: RemoteViews.InteractionHandler,
+ private val interactionHandler: RemoteViews.InteractionHandler,
looper: Looper,
logBuffer: LogBuffer,
) : AppWidgetHost(context, hostId, interactionHandler, looper) {
@@ -55,7 +55,7 @@
appWidgetId: Int,
appWidget: AppWidgetProviderInfo?
): AppWidgetHostView {
- return CommunalAppWidgetHostView(context)
+ return CommunalAppWidgetHostView(context, interactionHandler)
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHostView.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHostView.kt
index 2559137..d549734 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHostView.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHostView.kt
@@ -17,17 +17,25 @@
package com.android.systemui.communal.widgets
import android.appwidget.AppWidgetHostView
+import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProviderInfo
import android.content.Context
+import android.content.pm.LauncherActivityInfo
+import android.content.pm.LauncherApps
import android.graphics.Outline
import android.graphics.Rect
import android.view.View
import android.view.ViewOutlineProvider
+import android.widget.RemoteViews
+import android.widget.RemoteViews.RemoteResponse
import com.android.systemui.animation.LaunchableView
import com.android.systemui.animation.LaunchableViewDelegate
/** AppWidgetHostView that displays in communal hub with support for rounded corners. */
-class CommunalAppWidgetHostView(context: Context) : AppWidgetHostView(context), LaunchableView {
+class CommunalAppWidgetHostView(
+ context: Context,
+ private val interactionHandler: RemoteViews.InteractionHandler,
+) : AppWidgetHostView(context, interactionHandler), LaunchableView {
private val launchableViewDelegate =
LaunchableViewDelegate(
this,
@@ -92,4 +100,26 @@
launchableViewDelegate.setShouldBlockVisibilityChanges(block)
override fun setVisibility(visibility: Int) = launchableViewDelegate.setVisibility(visibility)
+
+ override fun onDefaultViewClicked(view: View) {
+ AppWidgetManager.getInstance(context)?.noteAppWidgetTapped(appWidgetId)
+ if (appWidgetInfo == null) {
+ return
+ }
+ val launcherApps = context.getSystemService(LauncherApps::class.java)
+ val activityInfo: LauncherActivityInfo =
+ launcherApps
+ .getActivityList(appWidgetInfo.provider.packageName, appWidgetInfo.profile)
+ ?.getOrNull(0) ?: return
+
+ val intent =
+ launcherApps.getMainActivityLaunchIntent(
+ activityInfo.componentName,
+ null,
+ activityInfo.user
+ )
+ if (intent != null) {
+ interactionHandler.onInteraction(view, intent, RemoteResponse.fromPendingIntent(intent))
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt
index 519903e..0eeb506 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt
@@ -25,6 +25,9 @@
import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor
import com.android.systemui.communal.util.InteractionHandlerDelegate
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.Logger
+import com.android.systemui.log.dagger.CommunalLog
import com.android.systemui.plugins.ActivityStarter
import javax.inject.Inject
@@ -33,14 +36,20 @@
@Inject
constructor(
private val activityStarter: ActivityStarter,
- private val communalSceneInteractor: CommunalSceneInteractor
+ communalSceneInteractor: CommunalSceneInteractor,
+ @CommunalLog val logBuffer: LogBuffer,
) : RemoteViews.InteractionHandler {
+ private companion object {
+ const val TAG = "WidgetInteractionHandler"
+ }
+
private val delegate =
InteractionHandlerDelegate(
communalSceneInteractor,
findViewToAnimate = { view -> view is CommunalAppWidgetHostView },
intentStarter = this::startIntent,
+ logger = Logger(logBuffer, TAG),
)
override fun onInteraction(
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java
index 7ced932..5a0eb72 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java
@@ -19,6 +19,7 @@
import android.content.BroadcastReceiver;
import com.android.systemui.GuestResetOrExitSessionReceiver;
+import com.android.systemui.accessibility.extradim.ExtraDimDialogReceiver;
import com.android.systemui.accessibility.hearingaid.HearingDevicesDialogReceiver;
import com.android.systemui.media.dialog.MediaOutputDialogReceiver;
import com.android.systemui.people.widget.PeopleSpaceWidgetPinnedReceiver;
@@ -88,4 +89,13 @@
@ClassKey(HearingDevicesDialogReceiver.class)
public abstract BroadcastReceiver bindHearingDevicesDialogReceiver(
HearingDevicesDialogReceiver broadcastReceiver);
+
+ /**
+ *
+ */
+ @Binds
+ @IntoMap
+ @ClassKey(ExtraDimDialogReceiver.class)
+ public abstract BroadcastReceiver bindExtraDimDialogReceiver(
+ ExtraDimDialogReceiver broadcastReceiver);
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index a448072..609aa39 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -103,6 +103,7 @@
import com.android.systemui.screenshot.dagger.ScreenshotModule;
import com.android.systemui.security.data.repository.SecurityRepositoryModule;
import com.android.systemui.settings.DisplayTracker;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
import com.android.systemui.shade.transition.LargeScreenShadeInterpolatorImpl;
@@ -154,6 +155,7 @@
import com.android.systemui.util.kotlin.SysUICoroutinesModule;
import com.android.systemui.util.reference.ReferenceModule;
import com.android.systemui.util.sensors.SensorModule;
+import com.android.systemui.util.settings.SettingsProxy;
import com.android.systemui.util.settings.SettingsUtilModule;
import com.android.systemui.util.time.SystemClock;
import com.android.systemui.util.time.SystemClockImpl;
@@ -268,15 +270,15 @@
NoteTaskModule.class,
WalletModule.class,
ContextualEducationModule.class
- },
+},
subcomponents = {
- ComplicationComponent.class,
- DozeComponent.class,
- ExpandableNotificationRowComponent.class,
- KeyguardBouncerComponent.class,
- NavigationBarComponent.class,
- NotificationRowComponent.class,
- WindowRootViewComponent.class,
+ ComplicationComponent.class,
+ DozeComponent.class,
+ ExpandableNotificationRowComponent.class,
+ KeyguardBouncerComponent.class,
+ NavigationBarComponent.class,
+ NotificationRowComponent.class,
+ WindowRootViewComponent.class,
})
public abstract class SystemUIModule {
@@ -443,4 +445,9 @@
@Binds
abstract SceneDataSource bindSceneDataSource(SceneDataSourceDelegator delegator);
+
+ @Provides
+ static SettingsProxy.CurrentUserIdProvider provideCurrentUserId(UserTracker userTracker) {
+ return userTracker::getUserId;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricsAllowedInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricsAllowedInteractor.kt
new file mode 100644
index 0000000..79b176c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricsAllowedInteractor.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.deviceentry.domain.interactor
+
+import com.android.systemui.biometrics.data.repository.FacePropertyRepository
+import com.android.systemui.biometrics.shared.model.SensorStrength
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+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
+
+/**
+ * Individual biometrics (ie: fingerprint or face) may not be allowed to be used based on the
+ * lockout states of biometrics of the same or higher sensor strength.
+ *
+ * This class coordinates the lockout states of each individual biometric based on the lockout
+ * states of other biometrics.
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+@SysUISingleton
+class DeviceEntryBiometricsAllowedInteractor
+@Inject
+constructor(
+ deviceEntryFingerprintAuthInteractor: DeviceEntryFingerprintAuthInteractor,
+ deviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor,
+ biometricSettingsInteractor: DeviceEntryBiometricSettingsInteractor,
+ facePropertyRepository: FacePropertyRepository,
+) {
+
+ private val isStrongFaceAuth: Flow<Boolean> =
+ facePropertyRepository.sensorInfo.map { it?.strength == SensorStrength.STRONG }
+
+ private val isStrongFaceAuthLockedOut: Flow<Boolean> =
+ combine(isStrongFaceAuth, deviceEntryFaceAuthInteractor.isLockedOut) {
+ isStrongFaceAuth,
+ isFaceAuthLockedOut ->
+ isStrongFaceAuth && isFaceAuthLockedOut
+ }
+
+ /**
+ * Whether fingerprint authentication is currently allowed for the user. This is true if the
+ * user has fingerprint auth enabled, enrolled, it is not disabled by any security timeouts by
+ * [com.android.systemui.keyguard.shared.model.AuthenticationFlags], not locked out due to too
+ * many incorrect attempts, and other biometrics at a higher or equal strenght are not locking
+ * fingerprint out.
+ */
+ val isFingerprintAuthCurrentlyAllowed: Flow<Boolean> =
+ combine(
+ deviceEntryFingerprintAuthInteractor.isLockedOut,
+ biometricSettingsInteractor.fingerprintAuthCurrentlyAllowed,
+ isStrongFaceAuthLockedOut,
+ ) { fpLockedOut, fpAllowedBySettings, strongAuthFaceAuthLockedOut ->
+ !fpLockedOut && fpAllowedBySettings && !strongAuthFaceAuthLockedOut
+ }
+
+ /** Whether fingerprint authentication is currently allowed while on the bouncer. */
+ val isFingerprintCurrentlyAllowedOnBouncer =
+ deviceEntryFingerprintAuthInteractor.isSensorUnderDisplay.flatMapLatest { sensorBelowDisplay
+ ->
+ if (sensorBelowDisplay) {
+ flowOf(false)
+ } else {
+ isFingerprintAuthCurrentlyAllowed
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFingerprintAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFingerprintAuthInteractor.kt
index a5eafa9..969f53f 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFingerprintAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFingerprintAuthInteractor.kt
@@ -29,10 +29,7 @@
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterIsInstance
-import kotlinx.coroutines.flow.flatMapLatest
-import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
@OptIn(ExperimentalCoroutinesApi::class)
@@ -70,29 +67,9 @@
repository.authenticationStatus.filterIsInstance<SuccessFingerprintAuthenticationStatus>()
/**
- * Whether fingerprint authentication is currently allowed for the user. This is true if the
- * user has fingerprint auth enabled, enrolled, it is not disabled by any security timeouts by
- * [com.android.systemui.keyguard.shared.model.AuthenticationFlags] and not locked out due to
- * too many incorrect attempts.
- */
- val isFingerprintAuthCurrentlyAllowed: Flow<Boolean> =
- combine(isLockedOut, biometricSettingsInteractor.fingerprintAuthCurrentlyAllowed, ::Pair)
- .map { (lockedOut, currentlyAllowed) -> !lockedOut && currentlyAllowed }
-
- /**
* Whether the fingerprint sensor is present under the display as opposed to being on the power
* button or behind/rear of the phone.
*/
val isSensorUnderDisplay =
fingerprintPropertyRepository.sensorType.map(FingerprintSensorType::isUdfps)
-
- /** Whether fingerprint authentication is currently allowed while on the bouncer. */
- val isFingerprintCurrentlyAllowedOnBouncer =
- isSensorUnderDisplay.flatMapLatest { sensorBelowDisplay ->
- if (sensorBelowDisplay) {
- flowOf(false)
- } else {
- isFingerprintAuthCurrentlyAllowed
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java b/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java
index e182d0b..f80e0be 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java
@@ -57,21 +57,29 @@
/**
- * Integer used to dim the screen while dozing.
+ * Integer in the scale [1, 255] used to dim the screen while dozing.
*
* @see R.integer.config_screenBrightnessDoze
*/
public int defaultDozeBrightness;
/**
- * Integer used to dim the screen just before the screen turns off.
+ * Integer in the scale [1, 255] used to dim the screen just before the screen turns off.
*
* @see R.integer.config_screenBrightnessDim
*/
public int dimBrightness;
/**
- * Integer array to map ambient brightness type to real screen brightness.
+ * Float in the scale [0, 1] used to dim the screen just before the screen turns off.
+ *
+ * @see R.integer.config_screenBrightnessDimFloat
+ */
+ public float dimBrightnessFloat;
+
+ /**
+ * Integer array to map ambient brightness type to real screen brightness in the integer scale
+ * [1, 255].
*
* @see Settings.Global#ALWAYS_ON_DISPLAY_CONSTANTS
* @see #KEY_SCREEN_BRIGHTNESS_ARRAY
@@ -189,6 +197,8 @@
com.android.internal.R.integer.config_screenBrightnessDoze);
dimBrightness = resources.getInteger(
com.android.internal.R.integer.config_screenBrightnessDim);
+ dimBrightnessFloat = resources.getFloat(
+ com.android.internal.R.dimen.config_screenBrightnessDimFloat);
screenBrightnessArray = mParser.getIntArray(KEY_SCREEN_BRIGHTNESS_ARRAY,
resources.getIntArray(
R.array.config_doze_brightness_sensor_to_brightness));
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeBrightnessHostForwarder.java b/packages/SystemUI/src/com/android/systemui/doze/DozeBrightnessHostForwarder.java
index cf0dcad..0b33614 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeBrightnessHostForwarder.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeBrightnessHostForwarder.java
@@ -36,4 +36,10 @@
super.setDozeScreenBrightness(brightness);
mHost.setDozeScreenBrightness(brightness);
}
+
+ @Override
+ public void setDozeScreenBrightnessFloat(float brightness) {
+ super.setDozeScreenBrightnessFloat(brightness);
+ mHost.setDozeScreenBrightnessFloat(brightness);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
index 17b455d..2e7a459 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
@@ -71,11 +71,17 @@
/**
* Sets the actual display brightness.
- * @param value from 0 to 255.
+ * @param value from 1 to 255.
*/
void setDozeScreenBrightness(int value);
/**
+ * Sets the actual display brightness.
+ * @param value from {@link PowerManager#BRIGHTNESS_MIN} to {@link PowerManager#BRIGHTNESS_MAX}.
+ */
+ void setDozeScreenBrightnessFloat(float value);
+
+ /**
* Fade out screen before switching off the display power mode.
* @param onDisplayOffCallback Executed when the display is black.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index 9a9e698..5bfcc97 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
@@ -401,13 +401,22 @@
/**
* Appends new AOD screen brightness to logs
- * @param brightness display brightness setting
+ * @param brightness display brightness setting between 1 and 255
*/
public void traceDozeScreenBrightness(int brightness) {
mLogger.logDozeScreenBrightness(brightness);
}
/**
+ * Appends new AOD screen brightness to logs
+ * @param brightness display brightness setting between {@link PowerManager#BRIGHTNESS_MIN} and
+ * {@link PowerManager#BRIGHTNESS_MAX}
+ */
+ public void traceDozeScreenBrightnessFloat(float brightness) {
+ mLogger.logDozeScreenBrightnessFloat(brightness);
+ }
+
+ /**
* Appends new AOD dimming scrim opacity to logs
* @param scrimOpacity
*/
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
index 9d6693e..a31dbec 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
@@ -309,7 +309,15 @@
buffer.log(TAG, INFO, {
int1 = brightness
}, {
- "Doze screen brightness set, brightness=$int1"
+ "Doze screen brightness set (int), brightness=$int1"
+ })
+ }
+
+ fun logDozeScreenBrightnessFloat(brightness: Float) {
+ buffer.log(TAG, INFO, {
+ double1 = brightness.toDouble()
+ }, {
+ "Doze screen brightness set (float), brightness=$double1"
})
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 7f0b16b..8198ef4 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -507,9 +507,13 @@
/** Request waking up. */
void requestWakeUp(@DozeLog.Reason int reason);
- /** Set screen brightness */
+ /** Set screen brightness between 1 and 255 */
void setDozeScreenBrightness(int brightness);
+ /** Set screen brightness between {@link PowerManager#BRIGHTNESS_MIN} and
+ * {@link PowerManager#BRIGHTNESS_MAX} */
+ void setDozeScreenBrightnessFloat(float brightness);
+
class Delegate implements Service {
private final Service mDelegate;
private final Executor mBgExecutor;
@@ -540,6 +544,13 @@
mDelegate.setDozeScreenBrightness(brightness);
});
}
+
+ @Override
+ public void setDozeScreenBrightnessFloat(float brightness) {
+ mBgExecutor.execute(() -> {
+ mDelegate.setDozeScreenBrightnessFloat(brightness);
+ });
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index 323ed98..89fce4a 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -20,6 +20,8 @@
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -27,6 +29,7 @@
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
+import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemProperties;
@@ -34,6 +37,7 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.util.IndentingPrintWriter;
+import android.view.Display;
import com.android.internal.R;
import com.android.systemui.doze.dagger.BrightnessSensor;
@@ -46,6 +50,7 @@
import com.android.systemui.util.settings.SystemSettings;
import java.io.PrintWriter;
+import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
@@ -74,6 +79,7 @@
private final DozeHost mDozeHost;
private final Handler mHandler;
private final SensorManager mSensorManager;
+ private final DisplayManager mDisplayManager;
private final Optional<Sensor>[] mLightSensorOptional; // light sensors to use per posture
private final WakefulnessLifecycle mWakefulnessLifecycle;
private final DozeParameters mDozeParameters;
@@ -81,13 +87,17 @@
private final DozeLog mDozeLog;
private final SystemSettings mSystemSettings;
private final int[] mSensorToBrightness;
+ @Nullable
+ private final float[] mSensorToBrightnessFloat;
private final int[] mSensorToScrimOpacity;
private final int mScreenBrightnessDim;
+ private final float mScreenBrightnessDimFloat;
@DevicePostureController.DevicePostureInt
private int mDevicePosture;
private boolean mRegistered;
private int mDefaultDozeBrightness;
+ private float mDefaultDozeBrightnessFloat;
private boolean mPaused = false;
private boolean mScreenOff = false;
private int mLastSensorValue = -1;
@@ -102,6 +112,7 @@
private int mDebugBrightnessBucket = -1;
@Inject
+ @SuppressLint("AndroidFrameworkRequiresPermission")
public DozeScreenBrightness(
Context context,
@WrappedService DozeMachine.Service service,
@@ -113,10 +124,12 @@
DozeParameters dozeParameters,
DevicePostureController devicePostureController,
DozeLog dozeLog,
- SystemSettings systemSettings) {
+ SystemSettings systemSettings,
+ DisplayManager displayManager) {
mContext = context;
mDozeService = service;
mSensorManager = sensorManager;
+ mDisplayManager = displayManager;
mLightSensorOptional = lightSensorOptional;
mDevicePostureController = devicePostureController;
mDevicePosture = mDevicePostureController.getDevicePosture();
@@ -131,8 +144,13 @@
R.dimen.config_screenBrightnessMinimumDimAmountFloat);
mDefaultDozeBrightness = alwaysOnDisplayPolicy.defaultDozeBrightness;
+ mDefaultDozeBrightnessFloat =
+ mDisplayManager.getDefaultDozeBrightness(mContext.getDisplayId());
mScreenBrightnessDim = alwaysOnDisplayPolicy.dimBrightness;
+ mScreenBrightnessDimFloat = alwaysOnDisplayPolicy.dimBrightnessFloat;
mSensorToBrightness = alwaysOnDisplayPolicy.screenBrightnessArray;
+ mSensorToBrightnessFloat =
+ mDisplayManager.getDozeBrightnessSensorValueToBrightness(mContext.getDisplayId());
mSensorToScrimOpacity = alwaysOnDisplayPolicy.dimmingScrimArray;
mDevicePostureController.addCallback(mDevicePostureCallback);
@@ -193,11 +211,22 @@
if (force || mRegistered || mDebugBrightnessBucket != -1) {
int sensorValue = mDebugBrightnessBucket == -1
? mLastSensorValue : mDebugBrightnessBucket;
- int brightness = computeBrightness(sensorValue);
- boolean brightnessReady = brightness > 0;
- if (brightnessReady) {
- mDozeService.setDozeScreenBrightness(
- clampToDimBrightnessForScreenOff(clampToUserSetting(brightness)));
+ boolean brightnessReady;
+ if (shouldUseFloatBrightness()) {
+ float brightness = computeBrightnessFloat(sensorValue);
+ brightnessReady = brightness >= 0;
+ if (brightnessReady) {
+ mDozeService.setDozeScreenBrightnessFloat(
+ clampToDimBrightnessForScreenOffFloat(
+ clampToUserSettingFloat(brightness)));
+ }
+ } else {
+ int brightness = computeBrightness(sensorValue);
+ brightnessReady = brightness > 0;
+ if (brightnessReady) {
+ mDozeService.setDozeScreenBrightness(
+ clampToDimBrightnessForScreenOff(clampToUserSetting(brightness)));
+ }
}
int scrimOpacity = -1;
@@ -249,17 +278,30 @@
return mSensorToBrightness[sensorValue];
}
+ private float computeBrightnessFloat(int sensorValue) {
+ if (sensorValue < 0 || sensorValue >= mSensorToBrightnessFloat.length) {
+ return -1;
+ }
+ return mSensorToBrightnessFloat[sensorValue];
+ }
+
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
private void resetBrightnessToDefault() {
- mDozeService.setDozeScreenBrightness(
- clampToDimBrightnessForScreenOff(
- clampToUserSetting(mDefaultDozeBrightness)));
+ if (shouldUseFloatBrightness()) {
+ mDozeService.setDozeScreenBrightnessFloat(
+ clampToDimBrightnessForScreenOffFloat(
+ clampToUserSettingOrAutoBrightnessFloat(mDefaultDozeBrightnessFloat)));
+ } else {
+ mDozeService.setDozeScreenBrightness(
+ clampToDimBrightnessForScreenOff(
+ clampToUserSettingOrAutoBrightness(mDefaultDozeBrightness)));
+ }
mDozeHost.setAodDimmingScrim(0f);
}
- //TODO: brightnessfloat change usages to float.
+
private int clampToUserSetting(int brightness) {
int screenBrightnessModeSetting = mSystemSettings.getIntForUser(
Settings.System.SCREEN_BRIGHTNESS_MODE,
@@ -268,10 +310,45 @@
return brightness;
}
- int userSetting = mSystemSettings.getIntForUser(
+ return Math.min(brightness, getScreenBrightness());
+ }
+
+ @SuppressLint("AndroidFrameworkRequiresPermission")
+ private float clampToUserSettingFloat(float brightness) {
+ int screenBrightnessModeSetting = mSystemSettings.getIntForUser(
+ Settings.System.SCREEN_BRIGHTNESS_MODE,
+ Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT);
+ if (screenBrightnessModeSetting == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC) {
+ return brightness;
+ }
+
+ return Math.min(brightness, getScreenBrightnessFloat());
+ }
+
+ private int clampToUserSettingOrAutoBrightness(int brightness) {
+ return Math.min(brightness, getScreenBrightness());
+ }
+
+ private float clampToUserSettingOrAutoBrightnessFloat(float brightness) {
+ return Math.min(brightness, getScreenBrightnessFloat());
+ }
+
+ /**
+ * Gets the current screen brightness that may have been set by manually by the user
+ * or by autobrightness.
+ */
+ private int getScreenBrightness() {
+ return mSystemSettings.getIntForUser(
Settings.System.SCREEN_BRIGHTNESS, Integer.MAX_VALUE,
UserHandle.USER_CURRENT);
- return Math.min(brightness, userSetting);
+ }
+
+ /**
+ * Gets the current screen brightness that may have been set by manually by the user
+ * or by autobrightness.
+ */
+ private float getScreenBrightnessFloat() {
+ return mDisplayManager.getBrightness(Display.DEFAULT_DISPLAY);
}
/**
@@ -301,6 +378,31 @@
}
}
+ /**
+ * Clamp the brightness to the dim brightness value used by PowerManagerService just before the
+ * device times out and goes to sleep, if we are sleeping from a timeout. This ensures that we
+ * don't raise the brightness back to the user setting before or during the screen off
+ * animation.
+ */
+ private float clampToDimBrightnessForScreenOffFloat(float brightness) {
+ final boolean screenTurningOff =
+ (mDozeParameters.shouldClampToDimBrightness()
+ || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_GOING_TO_SLEEP)
+ && mState == DozeMachine.State.INITIALIZED;
+ if (screenTurningOff
+ && mWakefulnessLifecycle.getLastSleepReason() == GO_TO_SLEEP_REASON_TIMEOUT) {
+ return Math.max(
+ PowerManager.BRIGHTNESS_MIN,
+ // Use the lower of either the dim brightness, or the current brightness reduced
+ // by the minimum dim amount. This is the same logic used in
+ // DisplayPowerController#updatePowerState to apply a minimum dim amount.
+ Math.min(brightness - mScreenBrightnessMinimumDimAmountFloat,
+ mScreenBrightnessDimFloat));
+ } else {
+ return brightness;
+ }
+ }
+
private void setLightSensorEnabled(boolean enabled) {
if (enabled && !mRegistered && isLightSensorPresent()) {
// Wait until we get an event from the sensor until indicating ready.
@@ -342,6 +444,20 @@
idpw.increaseIndent();
idpw.println("registered=" + mRegistered);
idpw.println("posture=" + DevicePostureController.devicePostureToString(mDevicePosture));
+ idpw.println("sensorToBrightness=" + Arrays.toString(mSensorToBrightness));
+ idpw.println("sensorToBrightnessFloat=" + Arrays.toString(mSensorToBrightnessFloat));
+ idpw.println("sensorToScrimOpacity=" + Arrays.toString(mSensorToScrimOpacity));
+ idpw.println("screenBrightnessDim=" + mScreenBrightnessDim);
+ idpw.println("screenBrightnessDimFloat=" + mScreenBrightnessDimFloat);
+ idpw.println("mDefaultDozeBrightness=" + mDefaultDozeBrightness);
+ idpw.println("mDefaultDozeBrightnessFloat=" + mDefaultDozeBrightnessFloat);
+ idpw.println("mLastSensorValue=" + mLastSensorValue);
+ idpw.println("shouldUseFloatBrightness()=" + shouldUseFloatBrightness());
+ }
+
+ private boolean shouldUseFloatBrightness() {
+ return com.android.server.display.feature.flags.Flags.dozeBrightnessFloat()
+ && mSensorToBrightnessFloat != null;
}
private final DevicePostureController.Callback mDevicePostureCallback =
diff --git a/packages/SystemUI/src/com/android/systemui/education/dagger/ContextualEducationModule.kt b/packages/SystemUI/src/com/android/systemui/education/dagger/ContextualEducationModule.kt
index b8019ab..532b123 100644
--- a/packages/SystemUI/src/com/android/systemui/education/dagger/ContextualEducationModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/education/dagger/ContextualEducationModule.kt
@@ -19,13 +19,13 @@
import com.android.systemui.CoreStartable
import com.android.systemui.Flags
import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.contextualeducation.GestureType
import com.android.systemui.education.data.repository.ContextualEducationRepository
import com.android.systemui.education.data.repository.ContextualEducationRepositoryImpl
import com.android.systemui.education.domain.interactor.ContextualEducationInteractor
import com.android.systemui.education.domain.interactor.KeyboardTouchpadEduInteractor
import com.android.systemui.education.domain.interactor.KeyboardTouchpadEduStatsInteractor
import com.android.systemui.education.domain.interactor.KeyboardTouchpadEduStatsInteractorImpl
-import com.android.systemui.shared.education.GestureType
import dagger.Binds
import dagger.Lazy
import dagger.Module
diff --git a/packages/SystemUI/src/com/android/systemui/education/data/repository/ContextualEducationRepository.kt b/packages/SystemUI/src/com/android/systemui/education/data/repository/ContextualEducationRepository.kt
index 248b7a5..52ccba4 100644
--- a/packages/SystemUI/src/com/android/systemui/education/data/repository/ContextualEducationRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/education/data/repository/ContextualEducationRepository.kt
@@ -17,9 +17,9 @@
package com.android.systemui.education.data.repository
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.contextualeducation.GestureType
import com.android.systemui.education.dagger.ContextualEducationModule.EduClock
import com.android.systemui.education.data.model.GestureEduModel
-import com.android.systemui.shared.education.GestureType
import java.time.Clock
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
diff --git a/packages/SystemUI/src/com/android/systemui/education/data/repository/UserContextualEducationRepository.kt b/packages/SystemUI/src/com/android/systemui/education/data/repository/UserContextualEducationRepository.kt
index b7fc773..4b37b29 100644
--- a/packages/SystemUI/src/com/android/systemui/education/data/repository/UserContextualEducationRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/education/data/repository/UserContextualEducationRepository.kt
@@ -27,9 +27,9 @@
import androidx.datastore.preferences.preferencesDataStoreFile
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.contextualeducation.GestureType
import com.android.systemui.education.dagger.ContextualEducationModule.EduDataStoreScope
import com.android.systemui.education.data.model.GestureEduModel
-import com.android.systemui.shared.education.GestureType
import java.time.Instant
import javax.inject.Inject
import javax.inject.Provider
diff --git a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/ContextualEducationInteractor.kt b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/ContextualEducationInteractor.kt
index 3036d97..bee289d 100644
--- a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/ContextualEducationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/ContextualEducationInteractor.kt
@@ -19,9 +19,10 @@
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.contextualeducation.GestureType
+import com.android.systemui.contextualeducation.GestureType.BACK
import com.android.systemui.education.data.model.GestureEduModel
import com.android.systemui.education.data.repository.ContextualEducationRepository
-import com.android.systemui.shared.education.GestureType
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
@@ -46,7 +47,7 @@
private val repository: ContextualEducationRepository,
) : CoreStartable {
- val backGestureModelFlow = readEduModelsOnSignalCountChanged(GestureType.BACK_GESTURE)
+ val backGestureModelFlow = readEduModelsOnSignalCountChanged(BACK)
override fun start() {
backgroundScope.launch {
diff --git a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
index 247abf1..9016c73 100644
--- a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
@@ -19,10 +19,10 @@
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.contextualeducation.GestureType.BACK
import com.android.systemui.education.data.model.GestureEduModel
import com.android.systemui.education.shared.model.EducationInfo
import com.android.systemui.education.shared.model.EducationUiType
-import com.android.systemui.shared.education.GestureType.BACK_GESTURE
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
@@ -50,7 +50,7 @@
backgroundScope.launch {
contextualEducationInteractor.backGestureModelFlow
.mapNotNull { getEduType(it) }
- .collect { _educationTriggered.value = EducationInfo(BACK_GESTURE, it) }
+ .collect { _educationTriggered.value = EducationInfo(BACK, it) }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduStatsInteractor.kt b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduStatsInteractor.kt
index 643e571..3223433 100644
--- a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduStatsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduStatsInteractor.kt
@@ -18,7 +18,7 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.shared.education.GestureType
+import com.android.systemui.contextualeducation.GestureType
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
diff --git a/packages/SystemUI/src/com/android/systemui/education/shared/model/EducationInfo.kt b/packages/SystemUI/src/com/android/systemui/education/shared/model/EducationInfo.kt
index 85f4012..d92fb9b 100644
--- a/packages/SystemUI/src/com/android/systemui/education/shared/model/EducationInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/education/shared/model/EducationInfo.kt
@@ -16,7 +16,7 @@
package com.android.systemui.education.shared.model
-import com.android.systemui.shared.education.GestureType
+import com.android.systemui.contextualeducation.GestureType
/**
* Model for education triggered. [gestureType] indicates what gesture it is trying to educate about
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
index 6e4038d..59de203 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
@@ -23,7 +23,13 @@
import com.android.server.notification.Flags.politeNotifications
import com.android.server.notification.Flags.vibrateWhileUnlocked
import com.android.systemui.Flags.FLAG_COMMUNAL_HUB
+import com.android.systemui.Flags.FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON
+import com.android.systemui.Flags.FLAG_STATUS_BAR_SCREEN_SHARING_CHIPS
+import com.android.systemui.Flags.FLAG_STATUS_BAR_USE_REPOS_FOR_CALL_CHIP
import com.android.systemui.Flags.communalHub
+import com.android.systemui.Flags.statusBarCallChipNotificationIcon
+import com.android.systemui.Flags.statusBarScreenSharingChips
+import com.android.systemui.Flags.statusBarUseReposForCallChip
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.KeyguardBottomAreaRefactor
import com.android.systemui.keyguard.MigrateClocksToBlueprint
@@ -38,9 +44,9 @@
import com.android.systemui.statusbar.notification.shared.NotificationAvalancheSuppression
import com.android.systemui.statusbar.notification.shared.NotificationIconContainerRefactor
import com.android.systemui.statusbar.notification.shared.NotificationMinimalismPrototype
+import com.android.systemui.statusbar.notification.shared.NotificationThrottleHun
import com.android.systemui.statusbar.notification.shared.NotificationsHeadsUpRefactor
import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
-import com.android.systemui.statusbar.notification.shared.NotificationThrottleHun
import com.android.systemui.statusbar.notification.shared.PriorityPeopleSection
import javax.inject.Inject
@@ -77,6 +83,10 @@
// QS Fragment using Compose dependencies
QSComposeFragment.token dependsOn NewQsUI.token
+
+ // Status bar chip dependencies
+ statusBarCallChipNotificationIconToken dependsOn statusBarUseReposForCallChipToken
+ statusBarCallChipNotificationIconToken dependsOn statusBarScreenSharingChipsToken
}
private inline val politeNotifications
@@ -96,4 +106,17 @@
private inline val communalHub
get() = FlagToken(FLAG_COMMUNAL_HUB, communalHub())
+
+ private inline val statusBarCallChipNotificationIconToken
+ get() =
+ FlagToken(
+ FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON,
+ statusBarCallChipNotificationIcon()
+ )
+
+ private inline val statusBarScreenSharingChipsToken
+ get() = FlagToken(FLAG_STATUS_BAR_SCREEN_SHARING_CHIPS, statusBarScreenSharingChips())
+
+ private inline val statusBarUseReposForCallChipToken
+ get() = FlagToken(FLAG_STATUS_BAR_USE_REPOS_FOR_CALL_CHIP, statusBarUseReposForCallChip())
}
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/KeyboardTouchpadOobeTutorialCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/KeyboardTouchpadOobeTutorialCoreStartable.kt
index dbfea76..701d3da 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/KeyboardTouchpadOobeTutorialCoreStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/KeyboardTouchpadOobeTutorialCoreStartable.kt
@@ -18,7 +18,7 @@
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.inputdevice.oobe.domain.interactor.OobeTutorialSchedulerInteractor
+import com.android.systemui.inputdevice.oobe.domain.interactor.OobeSchedulerInteractor
import com.android.systemui.shared.Flags.newTouchpadGesturesTutorial
import dagger.Lazy
import javax.inject.Inject
@@ -27,11 +27,10 @@
@SysUISingleton
class KeyboardTouchpadOobeTutorialCoreStartable
@Inject
-constructor(private val oobeTutorialSchedulerInteractor: Lazy<OobeTutorialSchedulerInteractor>) :
- CoreStartable {
+constructor(private val oobeSchedulerInteractor: Lazy<OobeSchedulerInteractor>) : CoreStartable {
override fun start() {
if (newTouchpadGesturesTutorial()) {
- oobeTutorialSchedulerInteractor.get().start()
+ oobeSchedulerInteractor.get().start()
}
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/data/model/OobeSchedulerInfo.kt
similarity index 61%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
copy to packages/SystemUI/src/com/android/systemui/inputdevice/oobe/data/model/OobeSchedulerInfo.kt
index 1f04a44..e5aedc0 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/data/model/OobeSchedulerInfo.kt
@@ -14,12 +14,14 @@
* limitations under the License.
*/
-package com.android.systemui.activatable
+package com.android.systemui.inputdevice.oobe.data.model
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.TestScope
+data class OobeSchedulerInfo(
+ val keyboard: DeviceSchedulerInfo = DeviceSchedulerInfo(),
+ val touchpad: DeviceSchedulerInfo = DeviceSchedulerInfo()
+)
-/** Activates [activatable] for the duration of the test. */
-fun Activatable.activateIn(testScope: TestScope) {
- testScope.backgroundScope.launch { activate() }
+data class DeviceSchedulerInfo(var isLaunched: Boolean = false, var connectionTime: Long? = null) {
+ val wasEverConnected: Boolean
+ get() = connectionTime != null
}
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/domain/interactor/OobeSchedulerInteractor.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/domain/interactor/OobeSchedulerInteractor.kt
new file mode 100644
index 0000000..b014c08
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/domain/interactor/OobeSchedulerInteractor.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.inputdevice.oobe.domain.interactor
+
+import android.content.Context
+import android.content.Intent
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.inputdevice.oobe.data.model.DeviceSchedulerInfo
+import com.android.systemui.inputdevice.oobe.data.model.OobeSchedulerInfo
+import com.android.systemui.keyboard.data.repository.KeyboardRepository
+import com.android.systemui.touchpad.data.repository.TouchpadRepository
+import java.time.Duration
+import java.time.Instant
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.launch
+
+/**
+ * When the first time a keyboard or touchpad id connected, wait for [LAUNCH_DELAY], then launch the
+ * tutorial as soon as there's a connected device
+ */
+@SysUISingleton
+class OobeSchedulerInteractor
+@Inject
+constructor(
+ @Application private val context: Context,
+ @Application private val applicationScope: CoroutineScope,
+ private val keyboardRepository: KeyboardRepository,
+ private val touchpadRepository: TouchpadRepository
+) {
+ private val info = OobeSchedulerInfo()
+
+ fun start() {
+ if (!info.keyboard.isLaunched) {
+ applicationScope.launch {
+ schedule(keyboardRepository.isAnyKeyboardConnected, info.keyboard)
+ }
+ }
+ if (!info.touchpad.isLaunched) {
+ applicationScope.launch {
+ schedule(touchpadRepository.isAnyTouchpadConnected, info.touchpad)
+ }
+ }
+ }
+
+ private suspend fun schedule(isAnyDeviceConnected: Flow<Boolean>, info: DeviceSchedulerInfo) {
+ if (!info.wasEverConnected) {
+ waitForDeviceConnection(isAnyDeviceConnected)
+ info.connectionTime = Instant.now().toEpochMilli()
+ }
+ delay(remainingTimeMillis(info.connectionTime!!))
+ waitForDeviceConnection(isAnyDeviceConnected)
+ info.isLaunched = true
+ launchOobe()
+ }
+
+ private suspend fun waitForDeviceConnection(isAnyDeviceConnected: Flow<Boolean>): Boolean {
+ return isAnyDeviceConnected.filter { it }.first()
+ }
+
+ private fun launchOobe() {
+ val intent = Intent(TUTORIAL_ACTION)
+ intent.addCategory(Intent.CATEGORY_DEFAULT)
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ context.startActivity(intent)
+ }
+
+ private fun remainingTimeMillis(start: Long): Long {
+ val elapsed = Instant.now().toEpochMilli() - start
+ return LAUNCH_DELAY - elapsed
+ }
+
+ companion object {
+ const val TAG = "OobeSchedulerInteractor"
+ const val TUTORIAL_ACTION = "com.android.systemui.action.TOUCHPAD_TUTORIAL"
+ private val LAUNCH_DELAY = Duration.ofHours(72).toMillis()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/domain/interactor/OobeTutorialSchedulerInteractor.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/domain/interactor/OobeTutorialSchedulerInteractor.kt
deleted file mode 100644
index 0d69081..0000000
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/domain/interactor/OobeTutorialSchedulerInteractor.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.inputdevice.oobe.domain.interactor
-
-import android.content.Context
-import android.content.Intent
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.keyboard.data.repository.KeyboardRepository
-import com.android.systemui.touchpad.data.repository.TouchpadRepository
-import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.launch
-
-/** When keyboards or touchpads are connected, schedule a tutorial after given time has elapsed */
-@SysUISingleton
-class OobeTutorialSchedulerInteractor
-@Inject
-constructor(
- @Application private val context: Context,
- @Application private val applicationScope: CoroutineScope,
- keyboardRepository: KeyboardRepository,
- touchpadRepository: TouchpadRepository
-) {
- private val isAnyKeyboardConnected = keyboardRepository.isAnyKeyboardConnected
- private val isAnyTouchpadConnected = touchpadRepository.isAnyTouchpadConnected
-
- fun start() {
- applicationScope.launch { isAnyKeyboardConnected.collect { startOobe() } }
- applicationScope.launch { isAnyTouchpadConnected.collect { startOobe() } }
- }
-
- private fun startOobe() {
- val intent = Intent(TUTORIAL_ACTION)
- intent.addCategory(Intent.CATEGORY_DEFAULT)
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- context.startActivity(intent)
- }
-
- companion object {
- const val TAG = "OobeSchedulerInteractor"
- const val TUTORIAL_ACTION = "com.android.systemui.action.TOUCHPAD_TUTORIAL"
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
index 58719fe..63f3d52 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
@@ -36,6 +36,7 @@
import androidx.compose.foundation.layout.FlowRowScope
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
@@ -208,9 +209,24 @@
Spacer(modifier = Modifier.height(6.dp))
ShortcutsSearchBar(onSearchQueryChanged)
Spacer(modifier = Modifier.height(16.dp))
- CategoriesPanelSinglePane(searchQuery, categories, selectedCategoryType, onCategorySelected)
- Spacer(modifier = Modifier.weight(1f))
- KeyboardSettings(onClick = onKeyboardSettingsClicked)
+ if (categories.isEmpty()) {
+ Box(modifier = Modifier.weight(1f)) {
+ NoSearchResultsText(horizontalPadding = 16.dp, fillHeight = true)
+ }
+ } else {
+ CategoriesPanelSinglePane(
+ searchQuery,
+ categories,
+ selectedCategoryType,
+ onCategorySelected
+ )
+ Spacer(modifier = Modifier.weight(1f))
+ }
+ KeyboardSettings(
+ horizontalPadding = 16.dp,
+ verticalPadding = 32.dp,
+ onClick = onKeyboardSettingsClicked
+ )
}
}
@@ -429,7 +445,7 @@
@Composable
private fun EndSidePanel(searchQuery: String, modifier: Modifier, category: ShortcutCategory?) {
if (category == null) {
- // TODO(b/353953351) - Show a "no results" UI?
+ NoSearchResultsText(horizontalPadding = 24.dp, fillHeight = false)
return
}
LazyColumn(modifier.nestedScroll(rememberNestedScrollInteropConnection())) {
@@ -441,6 +457,24 @@
}
@Composable
+private fun NoSearchResultsText(horizontalPadding: Dp, fillHeight: Boolean) {
+ var modifier = Modifier.fillMaxWidth()
+ if (fillHeight) {
+ modifier = modifier.fillMaxHeight()
+ }
+ Text(
+ stringResource(R.string.shortcut_helper_no_search_results),
+ style = MaterialTheme.typography.bodyMedium,
+ color = MaterialTheme.colorScheme.onSurface,
+ modifier =
+ modifier
+ .padding(vertical = 8.dp)
+ .background(MaterialTheme.colorScheme.surfaceBright, RoundedCornerShape(28.dp))
+ .padding(horizontal = horizontalPadding, vertical = 24.dp)
+ )
+}
+
+@Composable
private fun SubCategoryContainerDualPane(searchQuery: String, subCategory: ShortcutSubCategory) {
Surface(
modifier = Modifier.fillMaxWidth(),
@@ -659,7 +693,11 @@
Spacer(modifier = Modifier.heightIn(8.dp))
CategoriesPanelTwoPane(categories, selectedCategory, onCategoryClicked)
Spacer(modifier = Modifier.weight(1f))
- KeyboardSettings(onKeyboardSettingsClicked)
+ KeyboardSettings(
+ horizontalPadding = 24.dp,
+ verticalPadding = 24.dp,
+ onKeyboardSettingsClicked
+ )
}
}
@@ -805,15 +843,27 @@
}
@Composable
-private fun KeyboardSettings(onClick: () -> Unit) {
+private fun KeyboardSettings(horizontalPadding: Dp, verticalPadding: Dp, onClick: () -> Unit) {
+ val interactionSource = remember { MutableInteractionSource() }
+ val isFocused by interactionSource.collectIsFocusedAsState()
Surface(
onClick = onClick,
shape = RoundedCornerShape(24.dp),
color = Color.Transparent,
- modifier = Modifier.semantics { role = Role.Button }.fillMaxWidth()
+ modifier =
+ Modifier.semantics { role = Role.Button }
+ .fillMaxWidth()
+ .focusable(interactionSource = interactionSource)
) {
Row(
- modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp),
+ modifier =
+ Modifier.padding(horizontal = 12.dp, vertical = 16.dp)
+ .outlineFocusModifier(
+ isFocused = isFocused,
+ focusColor = MaterialTheme.colorScheme.secondary,
+ padding = 8.dp,
+ cornerRadius = 28.dp
+ ),
verticalAlignment = Alignment.CenterVertically
) {
Text(
@@ -821,11 +871,12 @@
color = MaterialTheme.colorScheme.onSurfaceVariant,
fontSize = 16.sp
)
- Spacer(modifier = Modifier.width(8.dp))
+ Spacer(modifier = Modifier.weight(1f))
Icon(
imageVector = Icons.AutoMirrored.Default.OpenInNew,
contentDescription = null,
- tint = MaterialTheme.colorScheme.onSurfaceVariant
+ tint = MaterialTheme.colorScheme.onSurfaceVariant,
+ modifier = Modifier.size(24.dp)
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
index aaeeb39..de60c11 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
@@ -105,7 +105,7 @@
* When the transition is over, TransitionState.FINISHED must be passed into the [state]
* parameter.
*/
- fun updateTransition(
+ suspend fun updateTransition(
transitionId: UUID,
@FloatRange(from = 0.0, to = 1.0) value: Float,
state: TransitionState
@@ -173,9 +173,9 @@
Log.d(TAG, "(Internal) Setting current transition info: $info")
// There is no fairness guarantee with 'withContext', which means that transitions could
- // be processed out of order. Use a Mutex to guarantee ordering.
+ // be processed out of order. Use a Mutex to guarantee ordering. [updateTransition]
+ // requires the same lock
_currentTransitionMutex.lock()
-
// Only used in a test environment
if (forceDelayForRaceConditionTest) {
delay(50L)
@@ -184,7 +184,6 @@
// Animators must be started on the main thread.
return withContext("$TAG#startTransition", mainDispatcher) {
_currentTransitionMutex.unlock()
-
if (lastStep.from == info.from && lastStep.to == info.to) {
Log.i(TAG, "Duplicate call to start the transition, rejecting: $info")
return@withContext null
@@ -206,7 +205,7 @@
// Cancel any existing manual transitions
updateTransitionId?.let { uuid ->
- updateTransition(uuid, lastStep.value, TransitionState.CANCELED)
+ updateTransitionInternal(uuid, lastStep.value, TransitionState.CANCELED)
}
info.animator?.let { animator ->
@@ -264,7 +263,23 @@
}
}
- override fun updateTransition(
+ override suspend fun updateTransition(
+ transitionId: UUID,
+ @FloatRange(from = 0.0, to = 1.0) value: Float,
+ state: TransitionState
+ ) {
+ // There is no fairness guarantee with 'withContext', which means that transitions could
+ // be processed out of order. Use a Mutex to guarantee ordering. [startTransition]
+ // requires the same lock
+ _currentTransitionMutex.lock()
+ withContext("$TAG#updateTransition", mainDispatcher) {
+ _currentTransitionMutex.unlock()
+
+ updateTransitionInternal(transitionId, value, state)
+ }
+ }
+
+ private suspend fun updateTransitionInternal(
transitionId: UUID,
@FloatRange(from = 0.0, to = 1.0) value: Float,
state: TransitionState
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
index e5ccc4a..2a8bb47 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
@@ -220,7 +220,10 @@
interpolator = Interpolators.LINEAR
duration =
when (toState) {
+ KeyguardState.GONE -> TO_GONE_DURATION
KeyguardState.LOCKSCREEN -> TO_LOCKSCREEN_DURATION
+ KeyguardState.OCCLUDED -> TO_OCCLUDED_DURATION
+ KeyguardState.PRIMARY_BOUNCER -> TO_PRIMARY_BOUNCER_DURATION
else -> DEFAULT_DURATION
}.inWholeMilliseconds
}
@@ -229,9 +232,9 @@
companion object {
private const val TAG = "FromAodTransitionInteractor"
private val DEFAULT_DURATION = 500.milliseconds
- val TO_LOCKSCREEN_DURATION = 500.milliseconds
val TO_GONE_DURATION = DEFAULT_DURATION
- val TO_OCCLUDED_DURATION = DEFAULT_DURATION
+ val TO_LOCKSCREEN_DURATION = 500.milliseconds
+ val TO_OCCLUDED_DURATION = 550.milliseconds
val TO_PRIMARY_BOUNCER_DURATION = DEFAULT_DURATION
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
index 8ef138e..61446c1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
@@ -302,16 +302,25 @@
override fun getDefaultAnimatorForTransitionsToState(toState: KeyguardState): ValueAnimator {
return ValueAnimator().apply {
interpolator = Interpolators.LINEAR
- duration = DEFAULT_DURATION.inWholeMilliseconds
+ duration =
+ when (toState) {
+ KeyguardState.GONE -> TO_GONE_DURATION
+ KeyguardState.GLANCEABLE_HUB -> TO_GLANCEABLE_HUB_DURATION
+ KeyguardState.LOCKSCREEN -> TO_LOCKSCREEN_DURATION
+ KeyguardState.OCCLUDED -> TO_OCCLUDED_DURATION
+ KeyguardState.PRIMARY_BOUNCER -> TO_PRIMARY_BOUNCER_DURATION
+ else -> DEFAULT_DURATION
+ }.inWholeMilliseconds
}
}
companion object {
const val TAG = "FromDozingTransitionInteractor"
private val DEFAULT_DURATION = 500.milliseconds
- val TO_LOCKSCREEN_DURATION = DEFAULT_DURATION
- val TO_GONE_DURATION = DEFAULT_DURATION
- val TO_PRIMARY_BOUNCER_DURATION = DEFAULT_DURATION
val TO_GLANCEABLE_HUB_DURATION = DEFAULT_DURATION
+ val TO_GONE_DURATION = DEFAULT_DURATION
+ val TO_LOCKSCREEN_DURATION = DEFAULT_DURATION
+ val TO_OCCLUDED_DURATION = 550.milliseconds
+ val TO_PRIMARY_BOUNCER_DURATION = DEFAULT_DURATION
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
index 91ee287..befcc9e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
@@ -96,6 +96,8 @@
when (toState) {
KeyguardState.LOCKSCREEN -> TO_LOCKSCREEN_DURATION
KeyguardState.OCCLUDED -> TO_OCCLUDED_DURATION
+ KeyguardState.ALTERNATE_BOUNCER -> TO_BOUNCER_DURATION
+ KeyguardState.PRIMARY_BOUNCER -> TO_BOUNCER_DURATION
else -> DEFAULT_DURATION
}.inWholeMilliseconds
}
@@ -269,8 +271,16 @@
companion object {
const val TAG = "FromGlanceableHubTransitionInteractor"
- val DEFAULT_DURATION = 1.seconds
- val TO_LOCKSCREEN_DURATION = DEFAULT_DURATION
+
+ /**
+ * DEFAULT_DURATION controls the timing for all animations other than those with overrides
+ * in [getDefaultAnimatorForTransitionsToState].
+ *
+ * Set at 400ms for parity with [FromLockscreenTransitionInteractor]
+ */
+ val DEFAULT_DURATION = 400.milliseconds
+ val TO_LOCKSCREEN_DURATION = 1.seconds
+ val TO_BOUNCER_DURATION = 400.milliseconds
val TO_OCCLUDED_DURATION = 450.milliseconds
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
index 206bbc5..51d92f0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
@@ -393,7 +393,7 @@
val TO_DOZING_DURATION = 500.milliseconds
val TO_DREAMING_DURATION = 933.milliseconds
val TO_DREAMING_HOSTED_DURATION = 933.milliseconds
- val TO_OCCLUDED_DURATION = 450.milliseconds
+ val TO_OCCLUDED_DURATION = 550.milliseconds
val TO_AOD_DURATION = 500.milliseconds
val TO_AOD_FOLD_DURATION = 1100.milliseconds
val TO_PRIMARY_BOUNCER_DURATION = DEFAULT_DURATION
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
index 04ea37e..2823b93 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
@@ -245,6 +245,7 @@
KeyguardState.GONE -> TO_GONE_DURATION
KeyguardState.LOCKSCREEN -> TO_LOCKSCREEN_DURATION
KeyguardState.GLANCEABLE_HUB -> TO_GLANCEABLE_HUB_DURATION
+ KeyguardState.OCCLUDED -> TO_OCCLUDED_DURATION
else -> DEFAULT_DURATION
}.inWholeMilliseconds
}
@@ -257,6 +258,7 @@
val TO_GONE_DURATION = 500.milliseconds
val TO_GONE_SHORT_DURATION = 200.milliseconds
val TO_LOCKSCREEN_DURATION = 450.milliseconds
+ val TO_OCCLUDED_DURATION = 550.milliseconds
val TO_GLANCEABLE_HUB_DURATION = DEFAULT_DURATION
val TO_GONE_SURFACE_BEHIND_VISIBLE_THRESHOLD = 0.1f
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/InternalKeyguardTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/InternalKeyguardTransitionInteractor.kt
index a51421c..2cc6afa 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/InternalKeyguardTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/InternalKeyguardTransitionInteractor.kt
@@ -63,7 +63,7 @@
suspend fun startTransition(info: TransitionInfo) = repository.startTransition(info)
- fun updateTransition(
+ suspend fun updateTransition(
transitionId: UUID,
@FloatRange(from = 0.0, to = 1.0) value: Float,
state: TransitionState
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
index 797d466..afbe357 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
@@ -47,6 +47,7 @@
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.buffer
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
@@ -55,6 +56,7 @@
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.flow.transform
import kotlinx.coroutines.launch
/** Encapsulates business-logic related to the keyguard transitions. */
@@ -150,6 +152,12 @@
startedStep.to != prevStep.from
) {
getTransitionValueFlow(prevStep.from).emit(0f)
+ } else if (prevStep.transitionState == TransitionState.RUNNING) {
+ Log.e(
+ TAG,
+ "STARTED step ($startedStep) was preceded by a RUNNING step " +
+ "($prevStep), which should never happen. Things could go badly here."
+ )
}
}
}
@@ -252,15 +260,12 @@
val startedKeyguardTransitionStep: Flow<TransitionStep> =
repository.transitions.filter { step -> step.transitionState == TransitionState.STARTED }
- /** The last [TransitionStep] with a [TransitionState] of FINISHED */
- val finishedKeyguardTransitionStep: Flow<TransitionStep> =
- repository.transitions.filter { step -> step.transitionState == TransitionState.FINISHED }
-
/** The destination state of the last [TransitionState.STARTED] transition. */
@SuppressLint("SharedFlowCreation")
val startedKeyguardState: SharedFlow<KeyguardState> =
startedKeyguardTransitionStep
.map { step -> step.to }
+ .buffer(2, BufferOverflow.DROP_OLDEST)
.shareIn(scope, SharingStarted.Eagerly, replay = 1)
/** The from state of the last [TransitionState.STARTED] transition. */
@@ -269,6 +274,7 @@
val startedKeyguardFromState: SharedFlow<KeyguardState> =
startedKeyguardTransitionStep
.map { step -> step.from }
+ .buffer(2, BufferOverflow.DROP_OLDEST)
.shareIn(scope, SharingStarted.Eagerly, replay = 1)
/** Which keyguard state to use when the device goes to sleep. */
@@ -310,8 +316,13 @@
*/
@SuppressLint("SharedFlowCreation")
val finishedKeyguardState: SharedFlow<KeyguardState> =
- finishedKeyguardTransitionStep
- .map { step -> step.to }
+ repository.transitions
+ .transform { step ->
+ if (step.transitionState == TransitionState.FINISHED) {
+ emit(step.to)
+ }
+ }
+ .buffer(2, BufferOverflow.DROP_OLDEST)
.shareIn(scope, SharingStarted.Eagerly, replay = 1)
/**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/scenetransition/LockscreenSceneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/scenetransition/LockscreenSceneTransitionInteractor.kt
index 3248114..b850095 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/scenetransition/LockscreenSceneTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/scenetransition/LockscreenSceneTransitionInteractor.kt
@@ -124,7 +124,7 @@
}
}
- private fun finishCurrentTransition() {
+ private suspend fun finishCurrentTransition() {
internalTransitionInteractor.updateTransition(currentTransitionId!!, 1f, FINISHED)
resetTransitionData()
}
@@ -223,7 +223,7 @@
currentTransitionId = internalTransitionInteractor.startTransition(transitionInfo)
}
- private fun updateProgress(progress: Float) {
+ private suspend fun updateProgress(progress: Float) {
if (currentTransitionId == null) return
internalTransitionInteractor.updateTransition(
currentTransitionId!!,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
index 23aa21c..0cb8dd4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
@@ -177,7 +177,12 @@
* Immediately (after 1ms) emits the given value for every step of the KeyguardTransition.
*/
fun immediatelyTransitionTo(value: Float): Flow<Float> {
- return sharedFlow(duration = 1.milliseconds, onStep = { value }, onFinish = { value })
+ return sharedFlow(
+ duration = 1.milliseconds,
+ onStep = { value },
+ onCancel = { value },
+ onFinish = { value }
+ )
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
index f96f053..91b66c3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
@@ -207,14 +207,12 @@
launch {
viewModel.burnInLayerVisibility.collect { visibility ->
childViews[burnInLayerId]?.visibility = visibility
- childViews[aodNotificationIconContainerId]?.visibility = visibility
}
}
launch {
viewModel.burnInLayerAlpha.collect { alpha ->
childViews[statusViewId]?.alpha = alpha
- childViews[aodNotificationIconContainerId]?.alpha = alpha
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModel.kt
index 9da11ce..c590f07 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModel.kt
@@ -51,6 +51,7 @@
transitionAnimation.sharedFlow(
duration = FromAlternateBouncerTransitionInteractor.TO_AOD_DURATION,
onStep = { 1 - it },
+ onCancel = { 0f },
onFinish = { 0f },
)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt
index b267ecb..6b22c0f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt
@@ -104,12 +104,10 @@
transitionAnimation.sharedFlow(
duration = 250.milliseconds,
onStep = { it },
+ onCancel = { 1f },
onFinish = { 1f },
)
override val deviceEntryParentViewAlpha: Flow<Float> =
- transitionAnimation.sharedFlow(
- duration = 500.milliseconds,
- onStep = { 1f },
- )
+ transitionAnimation.immediatelyTransitionTo(1f)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToAodTransitionViewModel.kt
index 1ee0368..7562392 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToAodTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToAodTransitionViewModel.kt
@@ -63,6 +63,7 @@
transitionAnimation.sharedFlow(
duration = FromDreamingTransitionInteractor.TO_AOD_DURATION,
onStep = { it },
+ onCancel = { 1f },
onFinish = { 1f },
)
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt
index ea8fe29..11ed52a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt
@@ -95,7 +95,7 @@
startTime = 167.milliseconds,
duration = 167.milliseconds,
onStep = { it },
- onCancel = { 0f },
+ onCancel = { 1f },
onFinish = { 1f },
)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
index 82381eb..b5ec7a6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
@@ -95,5 +95,11 @@
)
val deviceEntryBackgroundViewAlpha = transitionAnimation.immediatelyTransitionTo(1f)
- override val deviceEntryParentViewAlpha = lockscreenAlpha
+ override val deviceEntryParentViewAlpha =
+ transitionAnimation.sharedFlow(
+ startTime = 233.milliseconds,
+ duration = 250.milliseconds,
+ onCancel = { 1f },
+ onStep = { it },
+ )
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModel.kt
index 76d5a8d..f69f996 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModel.kt
@@ -93,7 +93,7 @@
transitionAnimation.sharedFlow(
duration = 167.milliseconds,
onStep = { 1 - it },
- onCancel = { 1f },
+ onCancel = { 0f },
onFinish = { 0f },
)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt
index 2bc8e51..43872b7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt
@@ -122,6 +122,7 @@
startTime = 1100.milliseconds,
duration = 200.milliseconds,
onStep = { it },
+ onCancel = { 1f },
onFinish = { 1f },
)
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToGlanceableHubTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToGlanceableHubTransitionViewModel.kt
index 6a3573a..6d95ade 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToGlanceableHubTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToGlanceableHubTransitionViewModel.kt
@@ -43,7 +43,7 @@
transitionAnimation.sharedFlow(
duration = 167.milliseconds,
onStep = { it },
- onCancel = { 0f },
+ onCancel = { 1f },
onFinish = { 1f },
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
index 11889c5..38a2b1b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
@@ -320,19 +320,24 @@
val isNotifIconContainerVisible: StateFlow<AnimatedValue<Boolean>> =
combine(
goneToAodTransitionRunning,
+ keyguardTransitionInteractor
+ .transitionValue(LOCKSCREEN)
+ .map { it > 0f }
+ .onStart { emit(false) },
keyguardTransitionInteractor.finishedKeyguardState.map {
KeyguardState.lockscreenVisibleInState(it)
},
deviceEntryInteractor.isBypassEnabled,
areNotifsFullyHiddenAnimated(),
isPulseExpandingAnimated(),
- ) {
- goneToAodTransitionRunning: Boolean,
- onKeyguard: Boolean,
- isBypassEnabled: Boolean,
- notifsFullyHidden: AnimatedValue<Boolean>,
- pulseExpanding: AnimatedValue<Boolean>,
- ->
+ ) { flows ->
+ val goneToAodTransitionRunning = flows[0] as Boolean
+ val isOnLockscreen = flows[1] as Boolean
+ val onKeyguard = flows[2] as Boolean
+ val isBypassEnabled = flows[3] as Boolean
+ val notifsFullyHidden = flows[4] as AnimatedValue<Boolean>
+ val pulseExpanding = flows[5] as AnimatedValue<Boolean>
+
when {
// Hide the AOD icons if we're not in the KEYGUARD state unless the screen off
// animation is playing, in which case we want them to be visible if we're
@@ -351,6 +356,8 @@
isBypassEnabled -> true
// If we are pulsing (and not bypassing), then we are hidden
isPulseExpanding -> false
+ // Besides bypass above, they should not be visible on lockscreen
+ isOnLockscreen -> false
// If notifs are fully gone, then we're visible
areNotifsFullyHidden -> true
// Otherwise, we're hidden
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt
index 5408428..2f21ebc 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt
@@ -70,6 +70,7 @@
transitionAnimation.sharedFlow(
duration = 300.milliseconds,
onStep = { 1 - it },
+ onCancel = { 0f },
onFinish = { 0f },
),
)
@@ -153,6 +154,7 @@
transitionAnimation.sharedFlow(
duration = 300.milliseconds,
onStep = { it },
+ onCancel = { 1f },
onFinish = { 1f },
),
flowWhenShadeIsNotExpanded = transitionAnimation.immediatelyTransitionTo(1f),
@@ -164,6 +166,7 @@
transitionAnimation.sharedFlow(
duration = 200.milliseconds,
onStep = { 1f - it },
+ onCancel = { 0f },
onFinish = { 0f },
),
)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
index 579abeb..bbb55cc 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
@@ -74,7 +74,12 @@
override val deviceEntryParentViewAlpha: Flow<Float> =
shadeDependentFlows.transitionFlow(
- flowWhenShadeIsNotExpanded = lockscreenAlpha,
+ flowWhenShadeIsNotExpanded =
+ transitionAnimation.sharedFlow(
+ duration = 250.milliseconds,
+ onStep = { 1f - it },
+ onCancel = { 0f },
+ ),
flowWhenShadeIsExpanded = transitionAnimation.immediatelyTransitionTo(0f),
)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModel.kt
index fcf8c14f..8d9ccef 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModel.kt
@@ -83,7 +83,12 @@
override val deviceEntryParentViewAlpha: Flow<Float> =
shadeDependentFlows.transitionFlow(
- flowWhenShadeIsNotExpanded = lockscreenAlpha,
+ flowWhenShadeIsNotExpanded =
+ transitionAnimation.sharedFlow(
+ duration = 250.milliseconds,
+ onStep = { 1f - it },
+ onCancel = { 0f },
+ ),
flowWhenShadeIsExpanded = transitionAnimation.immediatelyTransitionTo(0f),
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt
index 23c44b0a..e64c614 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt
@@ -65,6 +65,7 @@
transitionAnimation.sharedFlow(
duration = 250.milliseconds,
onStep = { 1f - it },
+ onCancel = { 0f },
onFinish = { 0f }
),
flowWhenShadeIsExpanded = transitionAnimation.immediatelyTransitionTo(0f)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
index 36c7d5b..737bd7a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
@@ -110,5 +110,11 @@
val deviceEntryBackgroundViewAlpha: Flow<Float> =
transitionAnimation.immediatelyTransitionTo(1f)
- override val deviceEntryParentViewAlpha: Flow<Float> = lockscreenAlpha
+ override val deviceEntryParentViewAlpha: Flow<Float> =
+ transitionAnimation.sharedFlow(
+ startTime = 233.milliseconds,
+ duration = 250.milliseconds,
+ onStep = { it },
+ onCancel = { 1f },
+ )
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModel.kt
index 009f85d..501feca 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModel.kt
@@ -70,6 +70,7 @@
transitionAnimation.sharedFlow(
duration = 300.milliseconds,
onStep = { it },
+ onCancel = { 1f },
onFinish = { 1f },
)
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/activatable/Activatable.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/Activatable.kt
similarity index 74%
rename from packages/SystemUI/src/com/android/systemui/activatable/Activatable.kt
rename to packages/SystemUI/src/com/android/systemui/lifecycle/Activatable.kt
index dc2d931..ebb0ea62 100644
--- a/packages/SystemUI/src/com/android/systemui/activatable/Activatable.kt
+++ b/packages/SystemUI/src/com/android/systemui/lifecycle/Activatable.kt
@@ -14,7 +14,11 @@
* limitations under the License.
*/
-package com.android.systemui.activatable
+package com.android.systemui.lifecycle
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.remember
/** Defines interface for classes that can be activated to do coroutine work. */
interface Activatable {
@@ -55,3 +59,20 @@
*/
suspend fun activate()
}
+
+/**
+ * Returns a remembered [Activatable] of the type [T] that's automatically kept active until this
+ * composable leaves the composition.
+ *
+ * If the [key] changes, the old [Activatable] is deactivated and a new one will be instantiated,
+ * activated, and returned.
+ */
+@Composable
+fun <T : Activatable> rememberActivated(
+ key: Any = Unit,
+ factory: () -> T,
+): T {
+ val instance = remember(key) { factory() }
+ LaunchedEffect(instance) { instance.activate() }
+ return instance
+}
diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
index bf80e18..661da6d 100644
--- a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
+++ b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
@@ -30,10 +30,21 @@
import com.android.systemui.Flags.coroutineTracing
import com.android.systemui.util.Assert
import com.android.systemui.util.Compile
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
+import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.DisposableHandle
+import kotlinx.coroutines.awaitCancellation
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onStart
/**
* Runs the given [block] every time the [View] becomes attached (or immediately after calling this
@@ -216,6 +227,102 @@
}
/**
+ * Runs the given [block] every time the [View] becomes attached (or immediately after calling this
+ * function, if the view was already attached), automatically canceling the work when the view
+ * becomes detached.
+ *
+ * Only use from the main thread.
+ *
+ * The [block] may be run multiple times, running once per every time the view is attached.
+ */
+@MainThread
+suspend fun View.repeatWhenAttachedToWindow(block: suspend CoroutineScope.() -> Unit): Nothing {
+ Assert.isMainThread()
+ isAttached.collectLatest { if (it) coroutineScope { block() } }
+ awaitCancellation() // satisfies return type of Nothing
+}
+
+/**
+ * Runs the given [block] every time the [Window] this [View] is attached to becomes visible (or
+ * immediately after calling this function, if the window is already visible), automatically
+ * canceling the work when the window becomes invisible.
+ *
+ * Only use from the main thread.
+ *
+ * The [block] may be run multiple times, running once per every time the window becomes visible.
+ */
+@MainThread
+suspend fun View.repeatWhenWindowIsVisible(block: suspend CoroutineScope.() -> Unit): Nothing {
+ Assert.isMainThread()
+ isWindowVisible.collectLatest { if (it) coroutineScope { block() } }
+ awaitCancellation() // satisfies return type of Nothing
+}
+
+/**
+ * Runs the given [block] every time the [Window] this [View] is attached to has focus (or
+ * immediately after calling this function, if the window is already focused), automatically
+ * canceling the work when the window loses focus.
+ *
+ * Only use from the main thread.
+ *
+ * The [block] may be run multiple times, running once per every time the window is focused.
+ */
+@MainThread
+suspend fun View.repeatWhenWindowHasFocus(block: suspend CoroutineScope.() -> Unit): Nothing {
+ Assert.isMainThread()
+ isWindowFocused.collectLatest { if (it) coroutineScope { block() } }
+ awaitCancellation() // satisfies return type of Nothing
+}
+
+private val View.isAttached
+ get() = conflatedCallbackFlow {
+ val onAttachListener =
+ object : View.OnAttachStateChangeListener {
+ override fun onViewAttachedToWindow(v: View) {
+ Assert.isMainThread()
+ trySend(true)
+ }
+
+ override fun onViewDetachedFromWindow(v: View) {
+ trySend(false)
+ }
+ }
+ addOnAttachStateChangeListener(onAttachListener)
+ trySend(isAttachedToWindow)
+ awaitClose { removeOnAttachStateChangeListener(onAttachListener) }
+ }
+
+private val View.currentViewTreeObserver: Flow<ViewTreeObserver?>
+ get() = isAttached.map { if (it) viewTreeObserver else null }
+
+private val View.isWindowVisible
+ get() =
+ currentViewTreeObserver.flatMapLatestConflated { vto ->
+ vto?.isWindowVisible?.onStart { emit(windowVisibility == View.VISIBLE) } ?: emptyFlow()
+ }
+
+private val View.isWindowFocused
+ get() =
+ currentViewTreeObserver.flatMapLatestConflated { vto ->
+ vto?.isWindowFocused?.onStart { emit(hasWindowFocus()) } ?: emptyFlow()
+ }
+
+private val ViewTreeObserver.isWindowFocused
+ get() = conflatedCallbackFlow {
+ val listener = ViewTreeObserver.OnWindowFocusChangeListener { trySend(it) }
+ addOnWindowFocusChangeListener(listener)
+ awaitClose { removeOnWindowFocusChangeListener(listener) }
+ }
+
+private val ViewTreeObserver.isWindowVisible
+ get() = conflatedCallbackFlow {
+ val listener =
+ ViewTreeObserver.OnWindowVisibilityChangeListener { v -> trySend(v == View.VISIBLE) }
+ addOnWindowVisibilityChangeListener(listener)
+ awaitClose { removeOnWindowVisibilityChangeListener(listener) }
+ }
+
+/**
* Even though there is only has one usage of `Dispatchers.Main` in this file, we cache it in a
* top-level property so that we do not unnecessarily create new `CoroutineContext` objects for
* tracing on each call to [repeatWhenAttached]. It is okay to reuse a single instance of the
diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/SafeActivatable.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/SafeActivatable.kt
new file mode 100644
index 0000000..f080a42
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/lifecycle/SafeActivatable.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.lifecycle
+
+import java.util.concurrent.atomic.AtomicBoolean
+
+/**
+ * An [Activatable] that can be concurrently activated by no more than one owner.
+ *
+ * A previous call to [activate] must be canceled before a new call to [activate] can be made.
+ * Trying to call [activate] while already active will fail with an error.
+ */
+abstract class SafeActivatable : Activatable {
+
+ private val _isActive = AtomicBoolean(false)
+
+ var isActive: Boolean
+ get() = _isActive.get()
+ private set(value) {
+ _isActive.set(value)
+ }
+
+ final override suspend fun activate() {
+ val allowed = _isActive.compareAndSet(false, true)
+ check(allowed) { "Cannot activate an already active activatable!" }
+
+ try {
+ onActivated()
+ } finally {
+ isActive = false
+ }
+ }
+
+ /**
+ * Notifies that the [Activatable] has been activated.
+ *
+ * Serves as an entrypoint to kick off coroutine work that the object requires in order to keep
+ * its state fresh and/or perform side-effects.
+ *
+ * The method suspends and doesn't return until all work required by the object is finished. In
+ * most cases, it's expected for the work to remain ongoing forever so this method will forever
+ * suspend its caller until the coroutine that called it is canceled.
+ *
+ * Implementations could follow this pattern:
+ * ```kotlin
+ * override suspend fun onActivated() {
+ * coroutineScope {
+ * launch { ... }
+ * launch { ... }
+ * launch { ... }
+ * }
+ * }
+ * ```
+ *
+ * @see activate
+ */
+ protected abstract suspend fun onActivated()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt
new file mode 100644
index 0000000..0af5fea
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.lifecycle
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.remember
+
+/** Base class for all System UI view-models. */
+abstract class SysUiViewModel : SafeActivatable() {
+
+ override suspend fun onActivated() = Unit
+}
+
+/**
+ * Returns a remembered [SysUiViewModel] of the type [T] that's automatically kept active until this
+ * composable leaves the composition.
+ *
+ * If the [key] changes, the old [SysUiViewModel] is deactivated and a new one will be instantiated,
+ * activated, and returned.
+ */
+@Composable
+fun <T : SysUiViewModel> rememberViewModel(
+ key: Any = Unit,
+ factory: () -> T,
+): T {
+ val instance = remember(key) { factory() }
+ LaunchedEffect(instance) { instance.activate() }
+ return instance
+}
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/MediaProjectionUtils.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/MediaProjectionUtils.kt
new file mode 100644
index 0000000..723ff5a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/MediaProjectionUtils.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.mediaprojection
+
+import android.content.pm.PackageManager
+import com.android.systemui.util.Utils
+
+/** Various utility methods related to media projection. */
+object MediaProjectionUtils {
+ /**
+ * Returns true iff projecting to the given [packageName] means that we're casting media to a
+ * *different* device (as opposed to sharing media to some application on *this* device).
+ */
+ fun packageHasCastingCapabilities(
+ packageManager: PackageManager,
+ packageName: String
+ ): Boolean {
+ // The [isHeadlessRemoteDisplayProvider] check approximates whether a projection is to a
+ // different device or the same device, because headless remote display packages are the
+ // only kinds of packages that do cast-to-other-device. This isn't exactly perfect,
+ // because it means that any projection by those headless remote display packages will be
+ // marked as going to a different device, even if that isn't always true. See b/321078669.
+ return Utils.isHeadlessRemoteDisplayProvider(packageManager, packageName)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java
index cc4a92c..3c83db3 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java
@@ -41,7 +41,6 @@
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
-import android.graphics.Typeface;
import android.media.projection.IMediaProjection;
import android.media.projection.MediaProjectionConfig;
import android.media.projection.MediaProjectionManager;
@@ -50,10 +49,8 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.text.BidiFormatter;
-import android.text.SpannableString;
import android.text.TextPaint;
import android.text.TextUtils;
-import android.text.style.StyleSpan;
import android.util.Log;
import android.view.Window;
@@ -61,6 +58,7 @@
import com.android.systemui.flags.Flags;
import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger;
import com.android.systemui.mediaprojection.MediaProjectionServiceHelper;
+import com.android.systemui.mediaprojection.MediaProjectionUtils;
import com.android.systemui.mediaprojection.SessionCreationSource;
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorActivity;
import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolver;
@@ -68,12 +66,13 @@
import com.android.systemui.res.R;
import com.android.systemui.statusbar.phone.AlertDialogWithDelegate;
import com.android.systemui.statusbar.phone.SystemUIDialog;
-import com.android.systemui.util.Utils;
-import dagger.Lazy;
+import java.util.function.Consumer;
import javax.inject.Inject;
+import dagger.Lazy;
+
public class MediaProjectionPermissionActivity extends Activity
implements DialogInterface.OnClickListener {
private static final String TAG = "MediaProjectionPermissionActivity";
@@ -189,30 +188,14 @@
final String appName = extractAppName(aInfo, packageManager);
final boolean hasCastingCapabilities =
- Utils.isHeadlessRemoteDisplayProvider(packageManager, mPackageName);
+ MediaProjectionUtils.INSTANCE.packageHasCastingCapabilities(
+ packageManager, mPackageName);
// Using application context for the dialog, instead of the activity context, so we get
// the correct screen width when in split screen.
Context dialogContext = getApplicationContext();
- final boolean overrideDisableSingleAppOption =
- CompatChanges.isChangeEnabled(
- OVERRIDE_DISABLE_MEDIA_PROJECTION_SINGLE_APP_OPTION,
- mPackageName, getHostUserHandle());
- MediaProjectionPermissionDialogDelegate delegate =
- new MediaProjectionPermissionDialogDelegate(
- dialogContext,
- getMediaProjectionConfig(),
- dialog -> {
- ScreenShareOption selectedOption =
- dialog.getSelectedScreenShareOption();
- grantMediaProjectionPermission(selectedOption.getMode());
- },
- () -> finish(RECORD_CANCEL, /* projection= */ null),
- hasCastingCapabilities,
- appName,
- overrideDisableSingleAppOption,
- mUid,
- mMediaProjectionMetricsLogger);
+ BaseMediaProjectionPermissionDialogDelegate<AlertDialog> delegate =
+ createPermissionDialogDelegate(appName, hasCastingCapabilities, dialogContext);
mDialog =
new AlertDialogWithDelegate(
dialogContext, R.style.Theme_SystemUI_Dialog, delegate);
@@ -274,6 +257,44 @@
return appName;
}
+ private BaseMediaProjectionPermissionDialogDelegate<AlertDialog> createPermissionDialogDelegate(
+ String appName,
+ boolean hasCastingCapabilities,
+ Context dialogContext) {
+ final boolean overrideDisableSingleAppOption =
+ CompatChanges.isChangeEnabled(
+ OVERRIDE_DISABLE_MEDIA_PROJECTION_SINGLE_APP_OPTION,
+ mPackageName, getHostUserHandle());
+ MediaProjectionConfig mediaProjectionConfig = getMediaProjectionConfig();
+ Consumer<BaseMediaProjectionPermissionDialogDelegate<AlertDialog>> onStartRecordingClicked =
+ dialog -> {
+ ScreenShareOption selectedOption = dialog.getSelectedScreenShareOption();
+ grantMediaProjectionPermission(selectedOption.getMode());
+ };
+ Runnable onCancelClicked = () -> finish(RECORD_CANCEL, /* projection= */ null);
+ if (hasCastingCapabilities) {
+ return new SystemCastPermissionDialogDelegate(
+ dialogContext,
+ mediaProjectionConfig,
+ onStartRecordingClicked,
+ onCancelClicked,
+ appName,
+ overrideDisableSingleAppOption,
+ mUid,
+ mMediaProjectionMetricsLogger);
+ } else {
+ return new ShareToAppPermissionDialogDelegate(
+ dialogContext,
+ mediaProjectionConfig,
+ onStartRecordingClicked,
+ onCancelClicked,
+ appName,
+ overrideDisableSingleAppOption,
+ mUid,
+ mMediaProjectionMetricsLogger);
+ }
+ }
+
@Override
protected void onDestroy() {
super.onDestroy();
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegate.kt
deleted file mode 100644
index 6d1a458..0000000
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegate.kt
+++ /dev/null
@@ -1,132 +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.mediaprojection.permission
-
-import android.app.AlertDialog
-import android.content.Context
-import android.media.projection.MediaProjectionConfig
-import android.os.Bundle
-import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger
-import com.android.systemui.res.R
-import java.util.function.Consumer
-
-/** Dialog to select screen recording options */
-class MediaProjectionPermissionDialogDelegate(
- context: Context,
- mediaProjectionConfig: MediaProjectionConfig?,
- private val onStartRecordingClicked: Consumer<MediaProjectionPermissionDialogDelegate>,
- private val onCancelClicked: Runnable,
- private val hasCastingCapabilities: Boolean,
- appName: String,
- forceShowPartialScreenshare: Boolean,
- hostUid: Int,
- mediaProjectionMetricsLogger: MediaProjectionMetricsLogger,
-) :
- BaseMediaProjectionPermissionDialogDelegate<AlertDialog>(
- createOptionList(
- context,
- appName,
- hasCastingCapabilities,
- mediaProjectionConfig,
- forceShowPartialScreenshare
- ),
- appName,
- hostUid,
- mediaProjectionMetricsLogger
- ) {
- override fun onCreate(dialog: AlertDialog, savedInstanceState: Bundle?) {
- super.onCreate(dialog, savedInstanceState)
- // TODO(b/270018943): Handle the case of System sharing (not recording nor casting)
- if (hasCastingCapabilities) {
- setDialogTitle(R.string.media_projection_entry_cast_permission_dialog_title)
- setStartButtonText(R.string.media_projection_entry_cast_permission_dialog_continue)
- } else {
- setDialogTitle(R.string.media_projection_entry_app_permission_dialog_title)
- setStartButtonText(R.string.media_projection_entry_app_permission_dialog_continue)
- }
- setStartButtonOnClickListener {
- // Note that it is important to run this callback before dismissing, so that the
- // callback can disable the dialog exit animation if it wants to.
- onStartRecordingClicked.accept(this)
- dialog.dismiss()
- }
- setCancelButtonOnClickListener {
- onCancelClicked.run()
- dialog.dismiss()
- }
- }
-
- companion object {
- private fun createOptionList(
- context: Context,
- appName: String,
- hasCastingCapabilities: Boolean,
- mediaProjectionConfig: MediaProjectionConfig?,
- overrideDisableSingleAppOption: Boolean = false,
- ): List<ScreenShareOption> {
- val singleAppWarningText =
- if (hasCastingCapabilities) {
- R.string.media_projection_entry_cast_permission_dialog_warning_single_app
- } else {
- R.string.media_projection_entry_app_permission_dialog_warning_single_app
- }
- val entireScreenWarningText =
- if (hasCastingCapabilities) {
- R.string.media_projection_entry_cast_permission_dialog_warning_entire_screen
- } else {
- R.string.media_projection_entry_app_permission_dialog_warning_entire_screen
- }
-
- // The single app option should only be disabled if the client has setup a
- // MediaProjection with MediaProjectionConfig#createConfigForDefaultDisplay AND
- // it hasn't been overridden by the OVERRIDE_DISABLE_SINGLE_APP_OPTION per-app override.
- val singleAppOptionDisabled =
- !overrideDisableSingleAppOption &&
- mediaProjectionConfig?.regionToCapture ==
- MediaProjectionConfig.CAPTURE_REGION_FIXED_DISPLAY
-
- val singleAppDisabledText =
- if (singleAppOptionDisabled) {
- context.getString(
- R.string.media_projection_entry_app_permission_dialog_single_app_disabled,
- appName
- )
- } else {
- null
- }
- val options =
- listOf(
- ScreenShareOption(
- mode = SINGLE_APP,
- spinnerText = R.string.screen_share_permission_dialog_option_single_app,
- warningText = singleAppWarningText,
- spinnerDisabledText = singleAppDisabledText,
- ),
- ScreenShareOption(
- mode = ENTIRE_SCREEN,
- spinnerText = R.string.screen_share_permission_dialog_option_entire_screen,
- warningText = entireScreenWarningText
- )
- )
- return if (singleAppOptionDisabled) {
- // Make sure "Entire screen" is the first option when "Single App" is disabled.
- options.reversed()
- } else {
- options
- }
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionUtils.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionUtils.kt
new file mode 100644
index 0000000..88cbc38
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionUtils.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.mediaprojection.permission
+
+import android.content.Context
+import android.media.projection.MediaProjectionConfig
+import com.android.systemui.res.R
+
+/** Various utility methods related to media projection permissions. */
+object MediaProjectionPermissionUtils {
+ fun getSingleAppDisabledText(
+ context: Context,
+ appName: String,
+ mediaProjectionConfig: MediaProjectionConfig?,
+ overrideDisableSingleAppOption: Boolean,
+ ): String? {
+ // The single app option should only be disabled if the client has setup a
+ // MediaProjection with MediaProjectionConfig#createConfigForDefaultDisplay AND
+ // it hasn't been overridden by the OVERRIDE_DISABLE_SINGLE_APP_OPTION per-app override.
+ val singleAppOptionDisabled =
+ !overrideDisableSingleAppOption &&
+ mediaProjectionConfig?.regionToCapture ==
+ MediaProjectionConfig.CAPTURE_REGION_FIXED_DISPLAY
+ return if (singleAppOptionDisabled) {
+ context.getString(
+ R.string.media_projection_entry_app_permission_dialog_single_app_disabled,
+ appName,
+ )
+ } else {
+ null
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/ShareToAppPermissionDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/ShareToAppPermissionDialogDelegate.kt
new file mode 100644
index 0000000..5a2d88c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/ShareToAppPermissionDialogDelegate.kt
@@ -0,0 +1,109 @@
+/*
+ * 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.mediaprojection.permission
+
+import android.app.AlertDialog
+import android.content.Context
+import android.media.projection.MediaProjectionConfig
+import android.os.Bundle
+import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger
+import com.android.systemui.res.R
+import java.util.function.Consumer
+
+/**
+ * Dialog to select screen recording options for sharing the screen to another app on the same
+ * device.
+ */
+class ShareToAppPermissionDialogDelegate(
+ context: Context,
+ mediaProjectionConfig: MediaProjectionConfig?,
+ private val onStartRecordingClicked:
+ Consumer<BaseMediaProjectionPermissionDialogDelegate<AlertDialog>>,
+ private val onCancelClicked: Runnable,
+ appName: String,
+ forceShowPartialScreenshare: Boolean,
+ hostUid: Int,
+ mediaProjectionMetricsLogger: MediaProjectionMetricsLogger,
+) :
+ BaseMediaProjectionPermissionDialogDelegate<AlertDialog>(
+ createOptionList(
+ context,
+ appName,
+ mediaProjectionConfig,
+ overrideDisableSingleAppOption = forceShowPartialScreenshare,
+ ),
+ appName,
+ hostUid,
+ mediaProjectionMetricsLogger,
+ ) {
+ override fun onCreate(dialog: AlertDialog, savedInstanceState: Bundle?) {
+ super.onCreate(dialog, savedInstanceState)
+ // TODO(b/270018943): Handle the case of System sharing (not recording nor casting)
+ setDialogTitle(R.string.media_projection_entry_app_permission_dialog_title)
+ setStartButtonText(R.string.media_projection_entry_app_permission_dialog_continue)
+ setStartButtonOnClickListener {
+ // Note that it is important to run this callback before dismissing, so that the
+ // callback can disable the dialog exit animation if it wants to.
+ onStartRecordingClicked.accept(this)
+ dialog.dismiss()
+ }
+ setCancelButtonOnClickListener {
+ onCancelClicked.run()
+ dialog.dismiss()
+ }
+ }
+
+ companion object {
+ private fun createOptionList(
+ context: Context,
+ appName: String,
+ mediaProjectionConfig: MediaProjectionConfig?,
+ overrideDisableSingleAppOption: Boolean,
+ ): List<ScreenShareOption> {
+ val singleAppDisabledText =
+ MediaProjectionPermissionUtils.getSingleAppDisabledText(
+ context,
+ appName,
+ mediaProjectionConfig,
+ overrideDisableSingleAppOption,
+ )
+ val options =
+ listOf(
+ ScreenShareOption(
+ mode = SINGLE_APP,
+ spinnerText = R.string.screen_share_permission_dialog_option_single_app,
+ warningText =
+ R.string
+ .media_projection_entry_app_permission_dialog_warning_single_app,
+ spinnerDisabledText = singleAppDisabledText,
+ ),
+ ScreenShareOption(
+ mode = ENTIRE_SCREEN,
+ spinnerText = R.string.screen_share_permission_dialog_option_entire_screen,
+ warningText =
+ R.string
+ .media_projection_entry_app_permission_dialog_warning_entire_screen,
+ )
+ )
+ return if (singleAppDisabledText != null) {
+ // Make sure "Entire screen" is the first option when "Single App" is disabled.
+ options.reversed()
+ } else {
+ options
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/SystemCastPermissionDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/SystemCastPermissionDialogDelegate.kt
new file mode 100644
index 0000000..1ac3ccd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/SystemCastPermissionDialogDelegate.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.mediaprojection.permission
+
+import android.app.AlertDialog
+import android.content.Context
+import android.media.projection.MediaProjectionConfig
+import android.os.Bundle
+import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger
+import com.android.systemui.mediaprojection.permission.MediaProjectionPermissionUtils.getSingleAppDisabledText
+import com.android.systemui.res.R
+import java.util.function.Consumer
+
+/** Dialog to select screen recording options for casting the screen to a different device. */
+class SystemCastPermissionDialogDelegate(
+ context: Context,
+ mediaProjectionConfig: MediaProjectionConfig?,
+ private val onStartRecordingClicked:
+ Consumer<BaseMediaProjectionPermissionDialogDelegate<AlertDialog>>,
+ private val onCancelClicked: Runnable,
+ appName: String,
+ forceShowPartialScreenshare: Boolean,
+ hostUid: Int,
+ mediaProjectionMetricsLogger: MediaProjectionMetricsLogger,
+) :
+ BaseMediaProjectionPermissionDialogDelegate<AlertDialog>(
+ createOptionList(
+ context,
+ appName,
+ mediaProjectionConfig,
+ overrideDisableSingleAppOption = forceShowPartialScreenshare,
+ ),
+ appName,
+ hostUid,
+ mediaProjectionMetricsLogger,
+ dialogIconDrawable = R.drawable.ic_cast_connected,
+ ) {
+ override fun onCreate(dialog: AlertDialog, savedInstanceState: Bundle?) {
+ super.onCreate(dialog, savedInstanceState)
+ // TODO(b/270018943): Handle the case of System sharing (not recording nor casting)
+ setDialogTitle(R.string.media_projection_entry_cast_permission_dialog_title)
+ setStartButtonText(R.string.media_projection_entry_cast_permission_dialog_continue)
+ setStartButtonOnClickListener {
+ // Note that it is important to run this callback before dismissing, so that the
+ // callback can disable the dialog exit animation if it wants to.
+ onStartRecordingClicked.accept(this)
+ dialog.dismiss()
+ }
+ setCancelButtonOnClickListener {
+ onCancelClicked.run()
+ dialog.dismiss()
+ }
+ }
+
+ companion object {
+ private fun createOptionList(
+ context: Context,
+ appName: String,
+ mediaProjectionConfig: MediaProjectionConfig?,
+ overrideDisableSingleAppOption: Boolean,
+ ): List<ScreenShareOption> {
+ val singleAppDisabledText =
+ getSingleAppDisabledText(
+ context,
+ appName,
+ mediaProjectionConfig,
+ overrideDisableSingleAppOption
+ )
+ val options =
+ listOf(
+ ScreenShareOption(
+ mode = SINGLE_APP,
+ spinnerText =
+ R.string
+ .media_projection_entry_cast_permission_dialog_option_text_single_app,
+ warningText =
+ R.string
+ .media_projection_entry_cast_permission_dialog_warning_single_app,
+ spinnerDisabledText = singleAppDisabledText,
+ ),
+ ScreenShareOption(
+ mode = ENTIRE_SCREEN,
+ spinnerText =
+ R.string
+ .media_projection_entry_cast_permission_dialog_option_text_entire_screen,
+ warningText =
+ R.string
+ .media_projection_entry_cast_permission_dialog_warning_entire_screen,
+ )
+ )
+ return if (singleAppDisabledText != null) {
+ // Make sure "Entire screen" is the first option when "Single App" is disabled.
+ options.reversed()
+ } else {
+ options
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java
index 1dbdec9..8e46fe4 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java
@@ -406,9 +406,8 @@
@Override
public void onViewAttachedToWindow(View v) {
if (result != null) {
- navBar.setImeWindowStatus(display.getDisplayId(), result.mImeToken,
- result.mImeWindowVis, result.mImeBackDisposition,
- result.mShowImeSwitcher);
+ navBar.setImeWindowStatus(display.getDisplayId(), result.mImeWindowVis,
+ result.mImeBackDisposition, result.mShowImeSwitcher);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index d022c1c..15b1e4d 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -42,7 +42,6 @@
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.inputmethodservice.InputMethodService;
-import android.os.IBinder;
import android.os.RemoteException;
import android.os.Trace;
import android.util.Log;
@@ -425,7 +424,7 @@
}
@Override
- public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
+ public void setImeWindowStatus(int displayId, int vis, int backDisposition,
boolean showImeSwitcher) {
boolean imeShown = mNavBarHelper.isImeShown(vis);
if (!imeShown) {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 9eca34f..0fe4d36 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -74,6 +74,7 @@
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.policy.GestureNavigationSettingsObserver;
import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.contextualeducation.GestureType;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.navigationbar.gestural.domain.GestureInteractor;
@@ -1057,6 +1058,8 @@
mEdgeBackPlugin.setIsLeftPanel(mIsOnLeftEdge);
mEdgeBackPlugin.onMotionEvent(ev);
dispatchToBackAnimation(ev);
+ mOverviewProxyService.updateContextualEduStats(mIsTrackpadThreeFingerSwipe,
+ GestureType.BACK);
}
if (mLogGesture || mIsTrackpadThreeFingerSwipe) {
mDownPoint.set(ev.getX(), ev.getY());
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java
index afdfa59..7b248eb 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java
@@ -71,7 +71,6 @@
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
-import android.os.IBinder;
import android.os.RemoteException;
import android.os.Trace;
import android.provider.DeviceConfig;
@@ -1095,7 +1094,7 @@
// ----- CommandQueue Callbacks -----
@Override
- public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
+ public void setImeWindowStatus(int displayId, int vis, int backDisposition,
boolean showImeSwitcher) {
if (displayId != mDisplayId) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningView.java b/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningView.java
index 1cd5d91..2ecca2d 100644
--- a/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningView.java
+++ b/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningView.java
@@ -16,6 +16,8 @@
package com.android.systemui.power;
+import static com.android.systemui.Flags.enableViewCaptureTracing;
+
import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.AnimatorListenerAdapter;
@@ -29,21 +31,27 @@
import android.view.WindowManager;
import android.widget.FrameLayout;
+import com.android.app.viewcapture.ViewCapture;
+import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
import com.android.systemui.res.R;
+import kotlin.Lazy;
+
/**
* View that shows a warning shortly before the device goes into sleep
* after prolonged user inactivity when bound to.
*/
public class InattentiveSleepWarningView extends FrameLayout {
private final IBinder mWindowToken = new Binder();
- private final WindowManager mWindowManager;
+ private final ViewCaptureAwareWindowManager mWindowManager;
private Animator mFadeOutAnimator;
private boolean mDismissing;
- InattentiveSleepWarningView(Context context) {
+ InattentiveSleepWarningView(Context context, Lazy<ViewCapture> lazyViewCapture) {
super(context);
- mWindowManager = mContext.getSystemService(WindowManager.class);
+ WindowManager wm = mContext.getSystemService(WindowManager.class);
+ mWindowManager = new ViewCaptureAwareWindowManager(wm, lazyViewCapture,
+ enableViewCaptureTracing());
final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
layoutInflater.inflate(R.layout.inattentive_sleep_warning, this, true /* attachToRoot */);
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 958ace35..861a7ce 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -16,6 +16,8 @@
package com.android.systemui.power;
+import static com.android.systemui.util.ConvenienceExtensionsKt.toKotlinLazy;
+
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -44,6 +46,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.app.viewcapture.ViewCapture;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.fuelgauge.Estimate;
import com.android.settingslib.utils.ThreadUtils;
@@ -56,6 +59,8 @@
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.ConfigurationController;
+import kotlin.Lazy;
+
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.concurrent.Future;
@@ -117,6 +122,7 @@
private final Context mContext;
private final BroadcastDispatcher mBroadcastDispatcher;
private final CommandQueue mCommandQueue;
+ private final Lazy<ViewCapture> mLazyViewCapture;
@Nullable
private final IVrManager mVrManager;
private final WakefulnessLifecycle.Observer mWakefulnessObserver =
@@ -157,7 +163,8 @@
EnhancedEstimates enhancedEstimates,
WakefulnessLifecycle wakefulnessLifecycle,
PowerManager powerManager,
- UserTracker userTracker) {
+ UserTracker userTracker,
+ dagger.Lazy<ViewCapture> daggerLazyViewCapture) {
mContext = context;
mBroadcastDispatcher = broadcastDispatcher;
mCommandQueue = commandQueue;
@@ -167,6 +174,7 @@
mPowerManager = powerManager;
mWakefulnessLifecycle = wakefulnessLifecycle;
mUserTracker = userTracker;
+ mLazyViewCapture = toKotlinLazy(daggerLazyViewCapture);
}
public void start() {
@@ -641,7 +649,7 @@
@Override
public void showInattentiveSleepWarning() {
if (mOverlayView == null) {
- mOverlayView = new InattentiveSleepWarningView(mContext);
+ mOverlayView = new InattentiveSleepWarningView(mContext, mLazyViewCapture);
}
mOverlayView.show();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragmentLegacy.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentLegacy.java
index 38d7290..37002ca 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragmentLegacy.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentLegacy.java
@@ -17,6 +17,7 @@
package com.android.systemui.qs;
import android.content.res.Configuration;
+import android.graphics.Rect;
import android.os.Bundle;
import android.os.Trace;
import android.view.ContextThemeWrapper;
@@ -30,6 +31,7 @@
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.qs.QSContainerController;
import com.android.systemui.qs.dagger.QSFragmentComponent;
+import com.android.systemui.qs.flags.QSComposeFragment;
import com.android.systemui.res.R;
import com.android.systemui.settings.brightness.MirrorController;
import com.android.systemui.util.LifecycleFragment;
@@ -103,6 +105,7 @@
@Override
public View getHeader() {
+ QSComposeFragment.assertInLegacyMode();
if (mQsImpl != null) {
return mQsImpl.getHeader();
} else {
@@ -111,6 +114,51 @@
}
@Override
+ public int getHeaderTop() {
+ if (mQsImpl != null) {
+ return mQsImpl.getHeaderTop();
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public int getHeaderBottom() {
+ if (mQsImpl != null) {
+ return mQsImpl.getHeaderBottom();
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public int getHeaderLeft() {
+ if (mQsImpl != null) {
+ return mQsImpl.getHeaderLeft();
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public void getHeaderBoundsOnScreen(Rect outBounds) {
+ if (mQsImpl != null) {
+ mQsImpl.getHeaderBoundsOnScreen(outBounds);
+ } else {
+ outBounds.setEmpty();
+ }
+ }
+
+ @Override
+ public boolean isHeaderShown() {
+ if (mQsImpl != null) {
+ return mQsImpl.isHeaderShown();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
public void setHasNotifications(boolean hasNotifications) {
if (mQsImpl != null) {
mQsImpl.setHasNotifications(hasNotifications);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java
index 8c0d122..a6fd35a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java
@@ -54,6 +54,7 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.dagger.QSComponent;
+import com.android.systemui.qs.flags.QSComposeFragment;
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.res.R;
@@ -355,10 +356,36 @@
@Override
public View getHeader() {
+ QSComposeFragment.assertInLegacyMode();
return mHeader;
}
@Override
+ public int getHeaderTop() {
+ return mHeader.getTop();
+ }
+
+ @Override
+ public int getHeaderBottom() {
+ return mHeader.getBottom();
+ }
+
+ @Override
+ public int getHeaderLeft() {
+ return mHeader.getLeft();
+ }
+
+ @Override
+ public void getHeaderBoundsOnScreen(Rect outBounds) {
+ mHeader.getBoundsOnScreen(outBounds);
+ }
+
+ @Override
+ public boolean isHeaderShown() {
+ return mHeader.isShown();
+ }
+
+ @Override
public void setHasNotifications(boolean hasNotifications) {
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt
index c6f9ae8..ddd0c76 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt
@@ -39,10 +39,10 @@
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collectIndexed
import kotlinx.coroutines.flow.filterNotNull
-import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.takeWhile
import kotlinx.coroutines.launch
// TODO(b/http://b/299909989): Use QSTileViewModel directly after the rollout
@@ -87,8 +87,9 @@
}
}
}
- // Warm up tile with some initial state
- launch { qsTileViewModel.state.first() }
+ // Warm up tile with some initial state. Because `state` is a StateFlow with initial
+ // state `null`, we collect until it's not null.
+ launch { qsTileViewModel.state.takeWhile { it == null }.collect {} }
}
// QSTileHost doesn't call this when userId is initialized
@@ -160,8 +161,8 @@
override fun setListening(client: Any?, listening: Boolean) {
client ?: return
if (listening) {
- listeningClients.add(client)
- if (listeningClients.size == 1) {
+ val clientWasNotAlreadyListening = listeningClients.add(client)
+ if (clientWasNotAlreadyListening && listeningClients.size == 1) {
stateJob =
qsTileViewModel.state
.filterNotNull()
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt
index bb36fd5..ae2f32a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt
@@ -24,6 +24,7 @@
import androidx.asynclayoutinflater.view.AsyncLayoutInflater
import com.android.settingslib.applications.InterestingConfigChanges
import com.android.systemui.Dumpable
+import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
@@ -196,6 +197,7 @@
private val qsSceneComponentFactory: QSSceneComponent.Factory,
private val qsImplProvider: Provider<QSImpl>,
shadeInteractor: ShadeInteractor,
+ displayStateInteractor: DisplayStateInteractor,
dumpManager: DumpManager,
@Main private val mainDispatcher: CoroutineDispatcher,
@Application applicationScope: CoroutineScope,
@@ -208,6 +210,7 @@
qsSceneComponentFactory: QSSceneComponent.Factory,
qsImplProvider: Provider<QSImpl>,
shadeInteractor: ShadeInteractor,
+ displayStateInteractor: DisplayStateInteractor,
dumpManager: DumpManager,
@Main dispatcher: CoroutineDispatcher,
@Application scope: CoroutineScope,
@@ -216,6 +219,7 @@
qsSceneComponentFactory,
qsImplProvider,
shadeInteractor,
+ displayStateInteractor,
dumpManager,
dispatcher,
scope,
@@ -319,6 +323,10 @@
qsImpl.value?.setInSplitShade(it == ShadeMode.Split)
}
}
+ launch {
+ combine(displayStateInteractor.isLargeScreen, qsImpl.filterNotNull(), ::Pair)
+ .collect { it.second.setIsNotificationPanelFullWidth(!it.first) }
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 371707d..15366d5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -89,6 +89,8 @@
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.contextualeducation.GestureType;
+import com.android.systemui.education.domain.interactor.KeyboardTouchpadEduStatsInteractor;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.KeyguardWmStateRefactor;
import com.android.systemui.keyguard.WakefulnessLifecycle;
@@ -160,6 +162,8 @@
private final NotificationShadeWindowController mStatusBarWinController;
private final Provider<SceneInteractor> mSceneInteractor;
+ private final KeyboardTouchpadEduStatsInteractor mKeyboardTouchpadEduStatsInteractor;
+
private final Runnable mConnectionRunnable = () ->
internalConnectToCurrentUser("runnable: startConnectionToCurrentUser");
private final ComponentName mRecentsComponentName;
@@ -661,7 +665,8 @@
AssistUtils assistUtils,
DumpManager dumpManager,
Optional<UnfoldTransitionProgressForwarder> unfoldTransitionProgressForwarder,
- BroadcastDispatcher broadcastDispatcher
+ BroadcastDispatcher broadcastDispatcher,
+ KeyboardTouchpadEduStatsInteractor keyboardTouchpadEduStatsInteractor
) {
// b/241601880: This component should only be running for primary users or
// secondaryUsers when visibleBackgroundUsers are supported.
@@ -698,6 +703,7 @@
mDisplayTracker = displayTracker;
mUnfoldTransitionProgressForwarder = unfoldTransitionProgressForwarder;
mBroadcastDispatcher = broadcastDispatcher;
+ mKeyboardTouchpadEduStatsInteractor = keyboardTouchpadEduStatsInteractor;
if (!KeyguardWmStateRefactor.isEnabled()) {
mSysuiUnlockAnimationController = sysuiUnlockAnimationController;
@@ -929,6 +935,19 @@
return isEnabled() && !QuickStepContract.isLegacyMode(mNavBarMode);
}
+ /**
+ * Updates contextual education stats when a gesture is triggered
+ * @param isTrackpadGesture indicates if the gesture is triggered by trackpad
+ * @param gestureType type of gesture triggered
+ */
+ public void updateContextualEduStats(boolean isTrackpadGesture, GestureType gestureType) {
+ if (isTrackpadGesture) {
+ mKeyboardTouchpadEduStatsInteractor.updateShortcutTriggerTime(gestureType);
+ } else {
+ mKeyboardTouchpadEduStatsInteractor.incrementSignalCount(gestureType);
+ }
+ }
+
public boolean isEnabled() {
return mIsEnabled;
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scene.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scene.kt
index c7190c3..103b4a5 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scene.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scene.kt
@@ -19,7 +19,7 @@
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
-import com.android.systemui.activatable.Activatable
+import com.android.systemui.lifecycle.Activatable
import kotlinx.coroutines.flow.Flow
/**
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotController.java
index a2583e6..a77375c 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotController.java
@@ -19,7 +19,6 @@
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
-import static com.android.systemui.Flags.screenshotPrivateProfileAccessibilityAnnouncementFix;
import static com.android.systemui.Flags.screenshotSaveImageExporter;
import static com.android.systemui.screenshot.LogConfig.DEBUG_ANIM;
import static com.android.systemui.screenshot.LogConfig.DEBUG_CALLBACK;
@@ -35,7 +34,6 @@
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.ICompatCameraControlCallback;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -356,19 +354,9 @@
void prepareViewForNewScreenshot(@NonNull ScreenshotData screenshot, String oldPackageName) {
withWindowAttached(() -> {
- if (screenshotPrivateProfileAccessibilityAnnouncementFix()) {
- mAnnouncementResolver.getScreenshotAnnouncement(
- screenshot.getUserHandle().getIdentifier(),
- mViewProxy::announceForAccessibility);
- } else {
- if (mUserManager.isManagedProfile(screenshot.getUserHandle().getIdentifier())) {
- mViewProxy.announceForAccessibility(mContext.getResources().getString(
- R.string.screenshot_saving_work_profile_title));
- } else {
- mViewProxy.announceForAccessibility(
- mContext.getResources().getString(R.string.screenshot_saving_title));
- }
- }
+ mAnnouncementResolver.getScreenshotAnnouncement(
+ screenshot.getUserHandle().getIdentifier(),
+ mViewProxy::announceForAccessibility);
});
mViewProxy.reset();
@@ -492,13 +480,6 @@
}
}
}
-
- @Override
- public void requestCompatCameraControl(boolean showControl,
- boolean transformationApplied,
- ICompatCameraControlCallback callback) {
- Log.w(TAG, "Unexpected requestCompatCameraControl callback");
- }
});
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 653e49f..540d4c4 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -19,7 +19,6 @@
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
-import static com.android.systemui.Flags.screenshotPrivateProfileAccessibilityAnnouncementFix;
import static com.android.systemui.Flags.screenshotSaveImageExporter;
import static com.android.systemui.screenshot.LogConfig.DEBUG_ANIM;
import static com.android.systemui.screenshot.LogConfig.DEBUG_CALLBACK;
@@ -35,7 +34,6 @@
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.ICompatCameraControlCallback;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -356,19 +354,11 @@
void prepareViewForNewScreenshot(@NonNull ScreenshotData screenshot, String oldPackageName) {
withWindowAttached(() -> {
- if (screenshotPrivateProfileAccessibilityAnnouncementFix()) {
- mAnnouncementResolver.getScreenshotAnnouncement(
- screenshot.getUserHandle().getIdentifier(),
- mViewProxy::announceForAccessibility);
- } else {
- if (mUserManager.isManagedProfile(screenshot.getUserHandle().getIdentifier())) {
- mViewProxy.announceForAccessibility(mContext.getResources().getString(
- R.string.screenshot_saving_work_profile_title));
- } else {
- mViewProxy.announceForAccessibility(
- mContext.getResources().getString(R.string.screenshot_saving_title));
- }
- }
+ mAnnouncementResolver.getScreenshotAnnouncement(
+ screenshot.getUserHandle().getIdentifier(),
+ announcement -> {
+ mViewProxy.announceForAccessibility(announcement);
+ });
});
mViewProxy.reset();
@@ -492,13 +482,6 @@
}
}
}
-
- @Override
- public void requestCompatCameraControl(boolean showControl,
- boolean transformationApplied,
- ICompatCameraControlCallback callback) {
- Log.w(TAG, "Unexpected requestCompatCameraControl callback");
- }
});
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 91bfae3..257390f 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -1305,10 +1305,6 @@
/** Updates the StatusBarViewController and updates any that depend on it. */
public void updateStatusViewController() {
// Re-associate the KeyguardStatusViewController
- if (mKeyguardStatusViewController != null) {
- mKeyguardStatusViewController.onDestroy();
- }
-
if (MigrateClocksToBlueprint.isEnabled()) {
// Need a shared controller until mKeyguardStatusViewController can be removed from
// here, due to important state being set in that controller. Rebind in order to pick
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
index b60c193..7e0454c 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
@@ -47,6 +47,7 @@
import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dumpable;
+import com.android.systemui.Flags;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.communal.domain.interactor.CommunalInteractor;
@@ -63,6 +64,7 @@
import com.android.systemui.scene.ui.view.WindowRootViewComponent;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.domain.interactor.ShadeInteractor;
+import com.android.systemui.shade.ui.viewmodel.NotificationShadeWindowModel;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -130,6 +132,7 @@
mCallbacks = new ArrayList<>();
private final SysuiColorExtractor mColorExtractor;
+ private final NotificationShadeWindowModel mNotificationShadeWindowModel;
/**
* Layout params would be aggregated and dispatched all at once if this is > 0.
*
@@ -162,6 +165,7 @@
ShadeWindowLogger logger,
Lazy<SelectedUserInteractor> userInteractor,
UserTracker userTracker,
+ NotificationShadeWindowModel notificationShadeWindowModel,
Lazy<CommunalInteractor> communalInteractor) {
mContext = context;
mWindowRootViewComponentFactory = windowRootViewComponentFactory;
@@ -176,6 +180,7 @@
mKeyguardBypassController = keyguardBypassController;
mBackgroundExecutor = backgroundExecutor;
mColorExtractor = colorExtractor;
+ mNotificationShadeWindowModel = notificationShadeWindowModel;
// prefix with {slow} to make sure this dumps at the END of the critical section.
dumpManager.registerCriticalDumpable("{slow}NotificationShadeWindowControllerImpl", this);
mAuthController = authController;
@@ -329,6 +334,14 @@
mCommunalInteractor.get().isCommunalVisible(),
this::onCommunalVisibleChanged
);
+
+ if (!SceneContainerFlag.isEnabled() && Flags.useTransitionsForKeyguardOccluded()) {
+ collectFlow(
+ mWindowRootView,
+ mNotificationShadeWindowModel.isKeyguardOccluded(),
+ this::setKeyguardOccluded
+ );
+ }
}
@Override
@@ -341,6 +354,11 @@
mScreenBrightnessDoze = value / 255f;
}
+ @Override
+ public void setDozeScreenBrightnessFloat(float value) {
+ mScreenBrightnessDoze = value;
+ }
+
private void setKeyguardDark(boolean dark) {
int vis = mWindowRootView.getSystemUiVisibility();
if (dark) {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt b/packages/SystemUI/src/com/android/systemui/shade/QSHeaderBoundsProvider.kt
similarity index 68%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
copy to packages/SystemUI/src/com/android/systemui/shade/QSHeaderBoundsProvider.kt
index 1f04a44..a447e55 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/QSHeaderBoundsProvider.kt
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package com.android.systemui.activatable
+package com.android.systemui.shade
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.TestScope
+import android.graphics.Rect
-/** Activates [activatable] for the duration of the test. */
-fun Activatable.activateIn(testScope: TestScope) {
- testScope.backgroundScope.launch { activate() }
-}
+class QSHeaderBoundsProvider(
+ val leftProvider: () -> Int,
+ val heightProvider: () -> Int,
+ val boundsOnScreenProvider: (Rect) -> Unit,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
index 67032f7..9f61d4e 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
@@ -43,7 +43,6 @@
import android.util.MathUtils;
import android.view.MotionEvent;
import android.view.VelocityTracker;
-import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowInsets;
@@ -75,6 +74,7 @@
import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.qs.flags.QSComposeFragment;
import com.android.systemui.res.R;
import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.screenrecord.RecordingController;
@@ -110,6 +110,8 @@
import dagger.Lazy;
+import kotlin.Unit;
+
import java.io.PrintWriter;
import javax.inject.Inject;
@@ -494,7 +496,15 @@
}
int getHeaderHeight() {
- return isQsFragmentCreated() ? mQs.getHeader().getHeight() : 0;
+ if (isQsFragmentCreated()) {
+ if (QSComposeFragment.isEnabled()) {
+ return mQs.getHeaderHeight();
+ } else {
+ return mQs.getHeader().getHeight();
+ }
+ } else {
+ return 0;
+ }
}
private boolean isRemoteInputActiveWithKeyboardUp() {
@@ -664,14 +674,26 @@
&& mKeyguardBypassController.getBypassEnabled()) || mSplitShadeEnabled) {
return false;
}
- View header = keyguardShowing || mQs == null ? mKeyguardStatusBar : mQs.getHeader();
+ int headerTop, headerBottom;
+ if (keyguardShowing || mQs == null) {
+ headerTop = mKeyguardStatusBar.getTop();
+ headerBottom = mKeyguardStatusBar.getBottom();
+ } else {
+ if (QSComposeFragment.isEnabled()) {
+ headerTop = mQs.getHeaderTop();
+ headerBottom = mQs.getHeaderBottom();
+ } else {
+ headerTop = mQs.getHeader().getTop();
+ headerBottom = mQs.getHeader().getBottom();
+ }
+ }
int frameTop = keyguardShowing
|| mQs == null ? 0 : mQsFrame.getTop();
mInterceptRegion.set(
/* left= */ (int) mQsFrame.getX(),
- /* top= */ header.getTop() + frameTop,
+ /* top= */ headerTop + frameTop,
/* right= */ (int) mQsFrame.getX() + mQsFrame.getWidth(),
- /* bottom= */ header.getBottom() + frameTop);
+ /* bottom= */ headerBottom + frameTop);
// Also allow QS to intercept if the touch is near the notch.
mStatusBarTouchableRegionManager.updateRegionForNotch(mInterceptRegion);
final boolean onHeader = mInterceptRegion.contains((int) x, (int) y);
@@ -718,9 +740,18 @@
if (mCollapsedOnDown || mBarState == KEYGUARD || getExpanded()) {
return false;
}
- View header = mQs == null ? mKeyguardStatusBar : mQs.getHeader();
+ int headerBottom;
+ if (mQs == null) {
+ headerBottom = mKeyguardStatusBar.getBottom();
+ } else {
+ if (QSComposeFragment.isEnabled()) {
+ headerBottom = mQs.getHeaderBottom();
+ } else {
+ headerBottom = mQs.getHeader().getBottom();
+ }
+ }
return downX >= mQsFrame.getX() && downX <= mQsFrame.getX() + mQsFrame.getWidth()
- && downY <= header.getBottom();
+ && downY <= headerBottom;
}
/** Closes the Qs customizer. */
@@ -2192,14 +2223,27 @@
}
});
mQs.setCollapsedMediaVisibilityChangedListener((visible) -> {
- if (mQs.getHeader().isShown()) {
+ if (mQs.isHeaderShown()) {
setAnimateNextNotificationBounds(
StackStateAnimator.ANIMATION_DURATION_STANDARD, 0);
mNotificationStackScrollLayoutController.animateNextTopPaddingChange();
}
});
mLockscreenShadeTransitionController.setQS(mQs);
- mNotificationStackScrollLayoutController.setQsHeader((ViewGroup) mQs.getHeader());
+ if (QSComposeFragment.isEnabled()) {
+ QSHeaderBoundsProvider provider = new QSHeaderBoundsProvider(
+ mQs::getHeaderLeft,
+ mQs::getHeaderHeight,
+ rect -> {
+ mQs.getHeaderBoundsOnScreen(rect);
+ return Unit.INSTANCE;
+ }
+ );
+
+ mNotificationStackScrollLayoutController.setQsHeaderBoundsProvider(provider);
+ } else {
+ mNotificationStackScrollLayoutController.setQsHeader((ViewGroup) mQs.getHeader());
+ }
mQs.setScrollListener(mQsScrollListener);
updateExpansion();
}
@@ -2211,6 +2255,9 @@
// non-fragment and fragment code. Once we are using a fragment for the notification
// panel, mQs will not need to be null cause it will be tied to the same lifecycle.
if (fragment == mQs) {
+ // Clear it to remove bindings to mQs from the provider.
+ mNotificationStackScrollLayoutController.setQsHeaderBoundsProvider(null);
+ mNotificationStackScrollLayoutController.setQsHeader(null);
mQs = null;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractor.kt
index 134c983..d1a0a6d 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractor.kt
@@ -17,6 +17,7 @@
package com.android.systemui.shade.domain.interactor
import com.android.systemui.shade.data.repository.ShadeAnimationRepository
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -38,4 +39,7 @@
* that is not considered "closing".
*/
abstract val isAnyCloseAnimationRunning: StateFlow<Boolean>
+
+ /** Whether a short animation to expand or collapse is running after user input has ended. */
+ abstract val isAnyFlingAnimationRunning: Flow<Boolean>
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorEmptyImpl.kt
index f364d6d..dbc1b3b 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorEmptyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorEmptyImpl.kt
@@ -20,6 +20,7 @@
import com.android.systemui.shade.data.repository.ShadeAnimationRepository
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
/** Implementation of ShadeAnimationInteractor for shadeless SysUI variants. */
@SysUISingleton
@@ -29,4 +30,5 @@
shadeAnimationRepository: ShadeAnimationRepository,
) : ShadeAnimationInteractor(shadeAnimationRepository) {
override val isAnyCloseAnimationRunning = MutableStateFlow(false)
+ override val isAnyFlingAnimationRunning = flowOf(false)
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorLegacyImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorLegacyImpl.kt
index c4f4134..32d8659 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorLegacyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorLegacyImpl.kt
@@ -20,6 +20,7 @@
import com.android.systemui.shade.data.repository.ShadeAnimationRepository
import com.android.systemui.shade.data.repository.ShadeRepository
import javax.inject.Inject
+import kotlinx.coroutines.flow.map
/** Implementation of ShadeAnimationInteractor compatible with NPVC. */
@SysUISingleton
@@ -30,4 +31,5 @@
shadeRepository: ShadeRepository,
) : ShadeAnimationInteractor(shadeAnimationRepository) {
override val isAnyCloseAnimationRunning = shadeRepository.legacyIsClosing
+ override val isAnyFlingAnimationRunning = shadeRepository.currentFling.map { it != null }
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImpl.kt
index d9982e3..79a94a5 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImpl.kt
@@ -36,12 +36,12 @@
@SysUISingleton
class ShadeAnimationInteractorSceneContainerImpl
@Inject
+@OptIn(ExperimentalCoroutinesApi::class)
constructor(
@Background scope: CoroutineScope,
shadeAnimationRepository: ShadeAnimationRepository,
sceneInteractor: SceneInteractor,
) : ShadeAnimationInteractor(shadeAnimationRepository) {
- @OptIn(ExperimentalCoroutinesApi::class)
override val isAnyCloseAnimationRunning =
sceneInteractor.transitionState
.flatMapLatest { state ->
@@ -62,4 +62,26 @@
}
.distinctUntilChanged()
.stateIn(scope, SharingStarted.Eagerly, false)
+
+ override val isAnyFlingAnimationRunning =
+ sceneInteractor.transitionState
+ .flatMapLatest { state ->
+ when (state) {
+ is ObservableTransitionState.Idle -> flowOf(false)
+ is ObservableTransitionState.Transition ->
+ if (
+ state.isInitiatedByUserInput &&
+ (state.fromScene == Scenes.Shade ||
+ state.toScene == Scenes.Shade ||
+ state.fromScene == Scenes.QuickSettings ||
+ state.toScene == Scenes.QuickSettings)
+ ) {
+ state.isUserInputOngoing.map { !it }
+ } else {
+ flowOf(false)
+ }
+ }
+ }
+ .distinctUntilChanged()
+ .stateIn(scope, SharingStarted.Eagerly, false)
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/startable/ShadeStartable.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/startable/ShadeStartable.kt
index 5eb3a1c..330f53f 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/startable/ShadeStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/startable/ShadeStartable.kt
@@ -18,6 +18,7 @@
import android.content.Context
import com.android.systemui.CoreStartable
+import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
import com.android.systemui.common.ui.data.repository.ConfigurationRepository
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
@@ -32,6 +33,7 @@
import com.android.systemui.shade.transition.ScrimShadeTransitionController
import com.android.systemui.statusbar.PulseExpansionHandler
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
+import com.android.systemui.statusbar.phone.ScrimController
import com.android.systemui.statusbar.policy.SplitShadeStateController
import javax.inject.Inject
import javax.inject.Provider
@@ -56,11 +58,14 @@
private val panelExpansionInteractorProvider: Provider<PanelExpansionInteractor>,
private val shadeExpansionStateManager: ShadeExpansionStateManager,
private val pulseExpansionHandler: PulseExpansionHandler,
+ private val displayStateInteractor: DisplayStateInteractor,
private val nsslc: NotificationStackScrollLayoutController,
+ private val scrimController: ScrimController,
) : CoreStartable {
override fun start() {
hydrateShadeLayoutWidth()
+ hydrateFullWidth()
hydrateShadeExpansionStateManager()
logTouchesTo(touchLog)
scrimShadeTransitionController.init()
@@ -98,4 +103,16 @@
}
}
}
+
+ private fun hydrateFullWidth() {
+ if (SceneContainerFlag.isEnabled) {
+ applicationScope.launch {
+ displayStateInteractor.isLargeScreen.collect {
+ val isFullWidth = !it
+ nsslc.setIsFullWidth(isFullWidth)
+ scrimController.setClipsQsScrim(isFullWidth)
+ }
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModel.kt
new file mode 100644
index 0000000..e1289af
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModel.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade.ui.viewmodel
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+
+/** Models UI state for the shade window. */
+@SysUISingleton
+class NotificationShadeWindowModel
+@Inject
+constructor(
+ keyguardTransitionInteractor: KeyguardTransitionInteractor,
+) {
+ val isKeyguardOccluded: Flow<Boolean> =
+ keyguardTransitionInteractor.transitionValue(OCCLUDED).map { it == 1f }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt
index f90dd3c..06298ef 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.shade.ui.viewmodel
import androidx.lifecycle.LifecycleOwner
@@ -24,8 +22,8 @@
import com.android.compose.animation.scene.SwipeDirection
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
-import com.android.systemui.activatable.Activatable
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.lifecycle.Activatable
import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
import com.android.systemui.qs.FooterActionsController
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
@@ -41,7 +39,6 @@
import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated
import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index b9d24ab..cea97d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -257,12 +257,11 @@
* Called to notify IME window status changes.
*
* @param displayId The id of the display to notify.
- * @param token IME token.
* @param vis IME visibility.
* @param backDisposition Disposition mode of back button. It should be one of below flags:
* @param showImeSwitcher {@code true} to show IME switch button.
*/
- default void setImeWindowStatus(int displayId, IBinder token, int vis,
+ default void setImeWindowStatus(int displayId, int vis,
@BackDispositionMode int backDisposition, boolean showImeSwitcher) { }
default void showRecentApps(boolean triggeredFromAltTab) { }
default void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { }
@@ -745,7 +744,7 @@
}
@Override
- public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
+ public void setImeWindowStatus(int displayId, int vis, int backDisposition,
boolean showImeSwitcher) {
synchronized (mLock) {
mHandler.removeMessages(MSG_SHOW_IME_BUTTON);
@@ -754,7 +753,6 @@
args.argi2 = vis;
args.argi3 = backDisposition;
args.argi4 = showImeSwitcher ? 1 : 0;
- args.arg1 = token;
Message m = mHandler.obtainMessage(MSG_SHOW_IME_BUTTON, args);
m.sendToTarget();
}
@@ -1208,7 +1206,7 @@
}
}
- private void handleShowImeButton(int displayId, IBinder token, int vis, int backDisposition,
+ private void handleShowImeButton(int displayId, int vis, int backDisposition,
boolean showImeSwitcher) {
if (displayId == INVALID_DISPLAY) return;
@@ -1224,17 +1222,15 @@
sendImeInvisibleStatusForPrevNavBar();
}
for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).setImeWindowStatus(displayId, token, vis, backDisposition,
- showImeSwitcher);
+ mCallbacks.get(i).setImeWindowStatus(displayId, vis, backDisposition, showImeSwitcher);
}
mLastUpdatedImeDisplayId = displayId;
}
private void sendImeInvisibleStatusForPrevNavBar() {
for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).setImeWindowStatus(mLastUpdatedImeDisplayId,
- null /* token */, IME_INVISIBLE, BACK_DISPOSITION_DEFAULT,
- false /* showImeSwitcher */);
+ mCallbacks.get(i).setImeWindowStatus(mLastUpdatedImeDisplayId, IME_INVISIBLE,
+ BACK_DISPOSITION_DEFAULT, false /* showImeSwitcher */);
}
}
@@ -1550,7 +1546,7 @@
break;
case MSG_SHOW_IME_BUTTON:
args = (SomeArgs) msg.obj;
- handleShowImeButton(args.argi1 /* displayId */, (IBinder) args.arg1 /* token */,
+ handleShowImeButton(args.argi1 /* displayId */,
args.argi2 /* vis */, args.argi3 /* backDisposition */,
args.argi4 != 0 /* showImeSwitcher */);
break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index bb26f92..7244f8a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar;
import static android.app.Flags.keyguardPrivateNotifications;
-import static android.app.Flags.redactSensitiveContentNotificationsOnLockscreen;
import static android.app.StatusBarManager.ACTION_KEYGUARD_PRIVATE_NOTIFICATIONS_CHANGED;
import static android.app.StatusBarManager.EXTRA_KM_PRIVATE_NOTIFS_ALLOWED;
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
@@ -72,6 +71,7 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
+import com.android.systemui.statusbar.notification.row.shared.LockscreenOtpRedaction;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.ListenerSet;
@@ -655,7 +655,7 @@
!userAllowsPrivateNotificationsInPublic(mCurrentUserId);
boolean isNotifForManagedProfile = mCurrentManagedProfiles.contains(userId);
boolean isNotifUserRedacted = !userAllowsPrivateNotificationsInPublic(userId);
- boolean isNotifSensitive = redactSensitiveContentNotificationsOnLockscreen()
+ boolean isNotifSensitive = LockscreenOtpRedaction.isEnabled()
&& ent.getRanking() != null && ent.getRanking().hasSensitiveContent();
// redact notifications if the current user is redacting notifications or the notification
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java
index 707d59aa..85fad42 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java
@@ -131,10 +131,20 @@
/** Sets the state of whether the remote input is active or not. */
default void onRemoteInputActive(boolean remoteInputActive) {}
- /** Sets the screen brightness level for when the device is dozing. */
+ /**
+ * Sets the screen brightness level for when the device is dozing.
+ * @param value The brightness value between 1 and 255
+ */
default void setDozeScreenBrightness(int value) {}
/**
+ * Sets the screen brightness level for when the device is dozing.
+ * @param value The brightness value between {@link PowerManager#BRIGHTNESS_MIN} and
+ * {@link PowerManager#BRIGHTNESS_MAX}
+ */
+ default void setDozeScreenBrightnessFloat(float value) {}
+
+ /**
* Sets whether the screen brightness is forced to the value we use for doze mode by the status
* bar window. No-op if the device does not support dozing.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/OWNERS b/packages/SystemUI/src/com/android/systemui/statusbar/OWNERS
new file mode 100644
index 0000000..69ebb76
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/OWNERS
@@ -0,0 +1,7 @@
+set noparent
+
+# Bug component: 78010
+
+caitlinshk@google.com
+evanlaird@google.com
+pixel@google.com
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
index 59fd0ca..18ea0b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
@@ -18,6 +18,7 @@
import android.view.View
import com.android.internal.jank.InteractionJankMonitor
+import com.android.systemui.Flags
import com.android.systemui.animation.ActivityTransitionAnimator
import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon
@@ -59,12 +60,24 @@
when (state) {
is OngoingCallModel.NoCall -> OngoingActivityChipModel.Hidden()
is OngoingCallModel.InCall -> {
+ val icon =
+ if (
+ Flags.statusBarCallChipNotificationIcon() &&
+ state.notificationIconView != null
+ ) {
+ OngoingActivityChipModel.ChipIcon.StatusBarView(
+ state.notificationIconView
+ )
+ } else {
+ OngoingActivityChipModel.ChipIcon.Basic(phoneIcon)
+ }
+
// This block mimics OngoingCallController#updateChip.
if (state.startTimeMs <= 0L) {
// If the start time is invalid, don't show a timer and show just an
// icon. See b/192379214.
OngoingActivityChipModel.Shown.IconOnly(
- icon = phoneIcon,
+ icon = icon,
colors = ColorsModel.Themed,
getOnClickListener(state),
)
@@ -73,7 +86,7 @@
state.startTimeMs - systemClock.currentTimeMillis() +
systemClock.elapsedRealtime()
OngoingActivityChipModel.Shown.Timer(
- icon = phoneIcon,
+ icon = icon,
colors = ColorsModel.Themed,
startTimeMs = startTimeInElapsedRealtime,
getOnClickListener(state),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModel.kt
index d9b0504..cf4e707 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModel.kt
@@ -190,12 +190,14 @@
): OngoingActivityChipModel.Shown {
return OngoingActivityChipModel.Shown.Timer(
icon =
- Icon.Resource(
- CAST_TO_OTHER_DEVICE_ICON,
- // This string is "Casting screen"
- ContentDescription.Resource(
- R.string.cast_screen_to_other_device_chip_accessibility_label,
- ),
+ OngoingActivityChipModel.ChipIcon.Basic(
+ Icon.Resource(
+ CAST_TO_OTHER_DEVICE_ICON,
+ // This string is "Casting screen"
+ ContentDescription.Resource(
+ R.string.cast_screen_to_other_device_chip_accessibility_label,
+ ),
+ )
),
colors = ColorsModel.Red,
// TODO(b/332662551): Maybe use a MediaProjection API to fetch this time.
@@ -213,10 +215,12 @@
private fun createIconOnlyCastChip(deviceName: String?): OngoingActivityChipModel.Shown {
return OngoingActivityChipModel.Shown.IconOnly(
icon =
- Icon.Resource(
- CAST_TO_OTHER_DEVICE_ICON,
- // This string is just "Casting"
- ContentDescription.Resource(R.string.accessibility_casting),
+ OngoingActivityChipModel.ChipIcon.Basic(
+ Icon.Resource(
+ CAST_TO_OTHER_DEVICE_ICON,
+ // This string is just "Casting"
+ ContentDescription.Resource(R.string.accessibility_casting),
+ )
),
colors = ColorsModel.Red,
createDialogLaunchOnClickListener(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/domain/interactor/MediaProjectionChipInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/domain/interactor/MediaProjectionChipInteractor.kt
index 191c221..c5f78d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/domain/interactor/MediaProjectionChipInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/domain/interactor/MediaProjectionChipInteractor.kt
@@ -21,11 +21,11 @@
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel
+import com.android.systemui.mediaprojection.MediaProjectionUtils.packageHasCastingCapabilities
import com.android.systemui.mediaprojection.data.model.MediaProjectionState
import com.android.systemui.mediaprojection.data.repository.MediaProjectionRepository
import com.android.systemui.statusbar.chips.StatusBarChipsLog
import com.android.systemui.statusbar.chips.mediaprojection.domain.model.ProjectionChipModel
-import com.android.systemui.util.Utils
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
@@ -60,7 +60,7 @@
}
is MediaProjectionState.Projecting -> {
val type =
- if (isProjectionToOtherDevice(state.hostPackage)) {
+ if (packageHasCastingCapabilities(packageManager, state.hostPackage)) {
ProjectionChipModel.Type.CAST_TO_OTHER_DEVICE
} else {
ProjectionChipModel.Type.SHARE_TO_APP
@@ -86,19 +86,6 @@
scope.launch { mediaProjectionRepository.stopProjecting() }
}
- /**
- * Returns true iff projecting to the given [packageName] means that we're projecting to a
- * *different* device (as opposed to projecting to some application on *this* device).
- */
- private fun isProjectionToOtherDevice(packageName: String?): Boolean {
- // The [isHeadlessRemoteDisplayProvider] check approximates whether a projection is to a
- // different device or the same device, because headless remote display packages are the
- // only kinds of packages that do cast-to-other-device. This isn't exactly perfect,
- // because it means that any projection by those headless remote display packages will be
- // marked as going to a different device, even if that isn't always true. See b/321078669.
- return Utils.isHeadlessRemoteDisplayProvider(packageManager, packageName)
- }
-
companion object {
private const val TAG = "MediaProjection"
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModel.kt
index fcf3de4..6ba4fef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModel.kt
@@ -78,11 +78,13 @@
is ScreenRecordChipModel.Recording -> {
OngoingActivityChipModel.Shown.Timer(
icon =
- Icon.Resource(
- ICON,
- ContentDescription.Resource(
- R.string.screenrecord_ongoing_screen_only,
- ),
+ OngoingActivityChipModel.ChipIcon.Basic(
+ Icon.Resource(
+ ICON,
+ ContentDescription.Resource(
+ R.string.screenrecord_ongoing_screen_only,
+ ),
+ )
),
colors = ColorsModel.Red,
startTimeMs = systemClock.elapsedRealtime(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModel.kt
index 85973fc..7897f93 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModel.kt
@@ -110,9 +110,11 @@
): OngoingActivityChipModel.Shown {
return OngoingActivityChipModel.Shown.Timer(
icon =
- Icon.Resource(
- SHARE_TO_APP_ICON,
- ContentDescription.Resource(R.string.share_to_app_chip_accessibility_label),
+ OngoingActivityChipModel.ChipIcon.Basic(
+ Icon.Resource(
+ SHARE_TO_APP_ICON,
+ ContentDescription.Resource(R.string.share_to_app_chip_accessibility_label),
+ )
),
colors = ColorsModel.Red,
// TODO(b/332662551): Maybe use a MediaProjection API to fetch this time.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt
index 17cf60b..26a2f91 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt
@@ -17,7 +17,9 @@
package com.android.systemui.statusbar.chips.ui.model
import android.view.View
+import com.android.systemui.Flags
import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.statusbar.StatusBarIconView
/** Model representing the display of an ongoing activity as a chip in the status bar. */
sealed class OngoingActivityChipModel {
@@ -38,7 +40,7 @@
/** This chip should be shown with the given information. */
abstract class Shown(
/** The icon to show on the chip. If null, no icon will be shown. */
- open val icon: Icon?,
+ open val icon: ChipIcon?,
/** What colors to use for the chip. */
open val colors: ColorsModel,
/**
@@ -50,7 +52,7 @@
/** This chip shows only an icon and nothing else. */
data class IconOnly(
- override val icon: Icon,
+ override val icon: ChipIcon,
override val colors: ColorsModel,
override val onClickListener: View.OnClickListener?,
) : Shown(icon, colors, onClickListener) {
@@ -59,7 +61,7 @@
/** The chip shows a timer, counting up from [startTimeMs]. */
data class Timer(
- override val icon: Icon,
+ override val icon: ChipIcon,
override val colors: ColorsModel,
/**
* The time this event started, used to show the timer.
@@ -88,4 +90,23 @@
override val logName = "Shown.Countdown"
}
}
+
+ /** Represents an icon to show on the chip. */
+ sealed interface ChipIcon {
+ /**
+ * The icon is a custom icon, which is set on [impl]. The icon was likely created by an
+ * external app.
+ */
+ data class StatusBarView(val impl: StatusBarIconView) : ChipIcon {
+ init {
+ check(Flags.statusBarCallChipNotificationIcon()) {
+ "OngoingActivityChipModel.ChipIcon.StatusBarView created even though " +
+ "Flags.statusBarCallChipNotificationIcon is not enabled"
+ }
+ }
+ }
+
+ /** The icon is a basic resource or drawable icon that System UI created internally. */
+ data class Basic(val impl: Icon) : ChipIcon
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
index 4a895c0..c52632e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
@@ -20,6 +20,7 @@
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED;
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED;
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE;
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_SINGLE_LINE;
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_GROUP_SUMMARY_HEADER;
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER;
@@ -54,6 +55,7 @@
import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation;
import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation;
+import com.android.systemui.statusbar.notification.row.shared.LockscreenOtpRedaction;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import javax.inject.Inject;
@@ -253,10 +255,11 @@
params.requireContentViews(FLAG_CONTENT_VIEW_EXPANDED);
params.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
params.setUseMinimized(isMinimized);
-
- if (screenshareNotificationHiding()
+ boolean needsRedaction = screenshareNotificationHiding()
? inflaterParams.getNeedsRedaction()
- : mNotificationLockscreenUserManager.needsRedaction(entry)) {
+ : mNotificationLockscreenUserManager.needsRedaction(entry);
+
+ if (needsRedaction) {
params.requireContentViews(FLAG_CONTENT_VIEW_PUBLIC);
} else {
params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC);
@@ -272,6 +275,14 @@
}
}
+ if (LockscreenOtpRedaction.isEnabled()) {
+ if (inflaterParams.isChildInGroup() && needsRedaction) {
+ params.requireContentViews(FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE);
+ } else {
+ params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE);
+ }
+ }
+
if (AsyncGroupHeaderViewInflation.isEnabled()) {
if (inflaterParams.isGroupSummary()) {
params.requireContentViews(FLAG_GROUP_SUMMARY_HEADER);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractor.kt
index 0dbc8c0..1cb59f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractor.kt
@@ -15,11 +15,13 @@
package com.android.systemui.statusbar.notification.domain.interactor
+import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.statusbar.notification.collection.render.NotifStats
import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
import com.android.systemui.statusbar.notification.shared.ActiveNotificationGroupModel
import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
+import com.android.systemui.statusbar.notification.shared.CallType
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
@@ -27,6 +29,7 @@
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
+@SysUISingleton
class ActiveNotificationsInteractor
@Inject
constructor(
@@ -71,6 +74,19 @@
val allNotificationsCountValue: Int
get() = repository.activeNotifications.value.individuals.size
+ /**
+ * The priority ongoing call notification, or null if there is no ongoing call.
+ *
+ * The output model is guaranteed to have [ActiveNotificationModel.callType] to be equal to
+ * [CallType.Ongoing].
+ */
+ val ongoingCallNotification: Flow<ActiveNotificationModel?> =
+ allRepresentativeNotifications.map { notifMap ->
+ // Once a call has started, its `whenTime` should stay the same, so we can use it as a
+ // stable sort value.
+ notifMap.values.filter { it.callType == CallType.Ongoing }.minByOrNull { it.whenTime }
+ }
+
/** Are any notifications being actively presented in the notification stack? */
val areAnyNotificationsPresent: Flow<Boolean> =
repository.activeNotifications
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractor.kt
index ab54bda..1008451 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractor.kt
@@ -15,9 +15,18 @@
*/
package com.android.systemui.statusbar.notification.domain.interactor
+import android.app.Notification.CallStyle.CALL_TYPE_INCOMING
+import android.app.Notification.CallStyle.CALL_TYPE_ONGOING
+import android.app.Notification.CallStyle.CALL_TYPE_SCREENING
+import android.app.Notification.CallStyle.CALL_TYPE_UNKNOWN
+import android.app.Notification.EXTRA_CALL_TYPE
+import android.app.PendingIntent
import android.graphics.drawable.Icon
+import android.service.notification.StatusBarNotification
import android.util.ArrayMap
import com.android.app.tracing.traceSection
+import com.android.systemui.Flags
+import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.notification.collection.GroupEntry
import com.android.systemui.statusbar.notification.collection.ListEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
@@ -27,6 +36,7 @@
import com.android.systemui.statusbar.notification.shared.ActiveNotificationEntryModel
import com.android.systemui.statusbar.notification.shared.ActiveNotificationGroupModel
import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
+import com.android.systemui.statusbar.notification.shared.CallType
import javax.inject.Inject
import kotlinx.coroutines.flow.update
@@ -120,10 +130,17 @@
return result
}
- private fun NotificationEntry.toModel(): ActiveNotificationModel =
- existingModels.createOrReuse(
+ private fun NotificationEntry.toModel(): ActiveNotificationModel {
+ val statusBarChipIcon =
+ if (Flags.statusBarCallChipNotificationIcon()) {
+ icons.statusBarChipIcon
+ } else {
+ null
+ }
+ return existingModels.createOrReuse(
key = key,
groupKey = sbn.groupKey,
+ whenTime = sbn.notification.`when`,
isAmbient = sectionStyleProvider.isMinimized(this),
isRowDismissed = isRowDismissed,
isSilent = sectionStyleProvider.isSilent(this),
@@ -133,17 +150,22 @@
aodIcon = icons.aodIcon?.sourceIcon,
shelfIcon = icons.shelfIcon?.sourceIcon,
statusBarIcon = icons.statusBarIcon?.sourceIcon,
+ statusBarChipIconView = statusBarChipIcon,
uid = sbn.uid,
packageName = sbn.packageName,
+ contentIntent = sbn.notification.contentIntent,
instanceId = sbn.instanceId?.id,
isGroupSummary = sbn.notification.isGroupSummary,
bucket = bucket,
+ callType = sbn.toCallType(),
)
+ }
}
private fun ActiveNotificationsStore.createOrReuse(
key: String,
groupKey: String?,
+ whenTime: Long,
isAmbient: Boolean,
isRowDismissed: Boolean,
isSilent: Boolean,
@@ -153,16 +175,20 @@
aodIcon: Icon?,
shelfIcon: Icon?,
statusBarIcon: Icon?,
+ statusBarChipIconView: StatusBarIconView?,
uid: Int,
packageName: String,
+ contentIntent: PendingIntent?,
instanceId: Int?,
isGroupSummary: Boolean,
bucket: Int,
+ callType: CallType,
): ActiveNotificationModel {
return individuals[key]?.takeIf {
it.isCurrent(
key = key,
groupKey = groupKey,
+ whenTime = whenTime,
isAmbient = isAmbient,
isRowDismissed = isRowDismissed,
isSilent = isSilent,
@@ -172,16 +198,20 @@
aodIcon = aodIcon,
shelfIcon = shelfIcon,
statusBarIcon = statusBarIcon,
+ statusBarChipIconView = statusBarChipIconView,
uid = uid,
instanceId = instanceId,
isGroupSummary = isGroupSummary,
packageName = packageName,
+ contentIntent = contentIntent,
bucket = bucket,
+ callType = callType,
)
}
?: ActiveNotificationModel(
key = key,
groupKey = groupKey,
+ whenTime = whenTime,
isAmbient = isAmbient,
isRowDismissed = isRowDismissed,
isSilent = isSilent,
@@ -191,17 +221,21 @@
aodIcon = aodIcon,
shelfIcon = shelfIcon,
statusBarIcon = statusBarIcon,
+ statusBarChipIconView = statusBarChipIconView,
uid = uid,
instanceId = instanceId,
isGroupSummary = isGroupSummary,
packageName = packageName,
+ contentIntent = contentIntent,
bucket = bucket,
+ callType = callType,
)
}
private fun ActiveNotificationModel.isCurrent(
key: String,
groupKey: String?,
+ whenTime: Long,
isAmbient: Boolean,
isRowDismissed: Boolean,
isSilent: Boolean,
@@ -211,15 +245,19 @@
aodIcon: Icon?,
shelfIcon: Icon?,
statusBarIcon: Icon?,
+ statusBarChipIconView: StatusBarIconView?,
uid: Int,
packageName: String,
+ contentIntent: PendingIntent?,
instanceId: Int?,
isGroupSummary: Boolean,
bucket: Int,
+ callType: CallType,
): Boolean {
return when {
key != this.key -> false
groupKey != this.groupKey -> false
+ whenTime != this.whenTime -> false
isAmbient != this.isAmbient -> false
isRowDismissed != this.isRowDismissed -> false
isSilent != this.isSilent -> false
@@ -229,11 +267,14 @@
aodIcon != this.aodIcon -> false
shelfIcon != this.shelfIcon -> false
statusBarIcon != this.statusBarIcon -> false
+ statusBarChipIconView != this.statusBarChipIconView -> false
uid != this.uid -> false
instanceId != this.instanceId -> false
isGroupSummary != this.isGroupSummary -> false
packageName != this.packageName -> false
+ contentIntent != this.contentIntent -> false
bucket != this.bucket -> false
+ callType != this.callType -> false
else -> true
}
}
@@ -259,3 +300,13 @@
else -> true
}
}
+
+private fun StatusBarNotification.toCallType(): CallType =
+ when (this.notification.extras.getInt(EXTRA_CALL_TYPE, -1)) {
+ -1 -> CallType.None
+ CALL_TYPE_INCOMING -> CallType.Incoming
+ CALL_TYPE_ONGOING -> CallType.Ongoing
+ CALL_TYPE_SCREENING -> CallType.Screening
+ CALL_TYPE_UNKNOWN -> CallType.Unknown
+ else -> CallType.Unknown
+ }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
index 331d3cc..dc6ab41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
@@ -123,6 +123,13 @@
// Construct the status bar icon view.
val sbIcon = iconBuilder.createIconView(entry)
sbIcon.scaleType = ImageView.ScaleType.CENTER_INSIDE
+ val sbChipIcon: StatusBarIconView?
+ if (Flags.statusBarCallChipNotificationIcon()) {
+ sbChipIcon = iconBuilder.createIconView(entry)
+ sbChipIcon.scaleType = ImageView.ScaleType.CENTER_INSIDE
+ } else {
+ sbChipIcon = null
+ }
// Construct the shelf icon view.
val shelfIcon = iconBuilder.createIconView(entry)
@@ -139,9 +146,19 @@
try {
setIcon(entry, normalIconDescriptor, sbIcon)
+ if (Flags.statusBarCallChipNotificationIcon() && sbChipIcon != null) {
+ setIcon(entry, normalIconDescriptor, sbChipIcon)
+ }
setIcon(entry, sensitiveIconDescriptor, shelfIcon)
setIcon(entry, sensitiveIconDescriptor, aodIcon)
- entry.icons = IconPack.buildPack(sbIcon, shelfIcon, aodIcon, entry.icons)
+ entry.icons =
+ IconPack.buildPack(
+ sbIcon,
+ sbChipIcon,
+ shelfIcon,
+ aodIcon,
+ entry.icons,
+ )
} catch (e: InflationException) {
entry.icons = IconPack.buildEmptyPack(entry.icons)
throw e
@@ -182,6 +199,11 @@
setIcon(entry, normalIconDescriptor, it)
}
+ entry.icons.statusBarChipIcon?.let {
+ it.setNotification(entry.sbn, notificationContentDescription)
+ setIcon(entry, normalIconDescriptor, it)
+ }
+
entry.icons.shelfIcon?.let {
it.setNotification(entry.sbn, notificationContentDescription)
setIcon(entry, sensitiveIconDescriptor, it)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconPack.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconPack.java
index d029ce7..611cebc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconPack.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconPack.java
@@ -29,6 +29,7 @@
private final boolean mAreIconsAvailable;
@Nullable private final StatusBarIconView mStatusBarIcon;
+ @Nullable private final StatusBarIconView mStatusBarChipIcon;
@Nullable private final StatusBarIconView mShelfIcon;
@Nullable private final StatusBarIconView mAodIcon;
@@ -43,7 +44,7 @@
* haven't been inflated yet or there was an error while inflating them).
*/
public static IconPack buildEmptyPack(@Nullable IconPack fromSource) {
- return new IconPack(false, null, null, null, fromSource);
+ return new IconPack(false, null, null, null, null, fromSource);
}
/**
@@ -51,20 +52,23 @@
*/
public static IconPack buildPack(
@NonNull StatusBarIconView statusBarIcon,
+ @Nullable StatusBarIconView statusBarChipIcon,
@NonNull StatusBarIconView shelfIcon,
@NonNull StatusBarIconView aodIcon,
@Nullable IconPack source) {
- return new IconPack(true, statusBarIcon, shelfIcon, aodIcon, source);
+ return new IconPack(true, statusBarIcon, statusBarChipIcon, shelfIcon, aodIcon, source);
}
private IconPack(
boolean areIconsAvailable,
@Nullable StatusBarIconView statusBarIcon,
+ @Nullable StatusBarIconView statusBarChipIcon,
@Nullable StatusBarIconView shelfIcon,
@Nullable StatusBarIconView aodIcon,
@Nullable IconPack source) {
mAreIconsAvailable = areIconsAvailable;
mStatusBarIcon = statusBarIcon;
+ mStatusBarChipIcon = statusBarChipIcon;
mShelfIcon = shelfIcon;
mAodIcon = aodIcon;
if (source != null) {
@@ -79,6 +83,17 @@
}
/**
+ * The version of the notification icon that appears inside a chip within the status bar.
+ *
+ * Separate from {@link #getStatusBarIcon()} so that we don't have to worry about detaching and
+ * re-attaching the same view when the chip appears and hides.
+ */
+ @Nullable
+ public StatusBarIconView getStatusBarChipIcon() {
+ return mStatusBarChipIcon;
+ }
+
+ /**
* The version of the icon that appears in the "shelf" at the bottom of the notification shade.
* In general, this icon also appears somewhere on the notification and is "sucked" into the
* shelf as the scrolls beyond it.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt
index a6ca3ab..17f401a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt
@@ -19,6 +19,9 @@
import android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST
import android.app.Notification
import android.app.Notification.BubbleMetadata
+import android.app.Notification.CATEGORY_ALARM
+import android.app.Notification.CATEGORY_CAR_EMERGENCY
+import android.app.Notification.CATEGORY_CAR_WARNING
import android.app.Notification.CATEGORY_EVENT
import android.app.Notification.CATEGORY_REMINDER
import android.app.Notification.VISIBILITY_PRIVATE
@@ -42,6 +45,7 @@
import android.service.notification.Flags
import com.android.internal.logging.UiEvent
import com.android.internal.logging.UiEventLogger
+import com.android.internal.logging.UiEventLogger.UiEventEnum.RESERVE_NEW_UI_EVENT_ID
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.statusbar.StatusBarStateController
@@ -307,6 +311,9 @@
ALLOW_CALLSTYLE,
ALLOW_CATEGORY_REMINDER,
ALLOW_CATEGORY_EVENT,
+ ALLOW_CATEGORY_ALARM,
+ ALLOW_CATEGORY_CAR_EMERGENCY,
+ ALLOW_CATEGORY_CAR_WARNING,
ALLOW_FSI_WITH_PERMISSION_ON,
ALLOW_COLORIZED,
ALLOW_EMERGENCY,
@@ -333,8 +340,13 @@
@UiEvent(doc = "HUN allowed during avalanche because it is colorized.")
AVALANCHE_SUPPRESSOR_HUN_ALLOWED_COLORIZED(1832),
@UiEvent(doc = "HUN allowed during avalanche because it is an emergency notification.")
- AVALANCHE_SUPPRESSOR_HUN_ALLOWED_EMERGENCY(1833);
-
+ AVALANCHE_SUPPRESSOR_HUN_ALLOWED_EMERGENCY(1833),
+ @UiEvent(doc = "HUN allowed during avalanche because it is an alarm.")
+ AVALANCHE_SUPPRESSOR_HUN_ALLOWED_CATEGORY_ALARM(1867),
+ @UiEvent(doc = "HUN allowed during avalanche because it is a car emergency.")
+ AVALANCHE_SUPPRESSOR_HUN_ALLOWED_CATEGORY_CAR_EMERGENCY(1868),
+ @UiEvent(doc = "HUN allowed during avalanche because it is a car warning")
+ AVALANCHE_SUPPRESSOR_HUN_ALLOWED_CATEGORY_CAR_WARNING(1869);
override fun getId(): Int {
return id
}
@@ -423,6 +435,22 @@
return State.ALLOW_CATEGORY_REMINDER
}
+ if (entry.sbn.notification.category == CATEGORY_ALARM) {
+ uiEventLogger.log(AvalancheEvent.AVALANCHE_SUPPRESSOR_HUN_ALLOWED_CATEGORY_ALARM)
+ return State.ALLOW_CATEGORY_ALARM
+ }
+
+ if (entry.sbn.notification.category == CATEGORY_CAR_EMERGENCY) {
+ uiEventLogger.log(
+ AvalancheEvent.AVALANCHE_SUPPRESSOR_HUN_ALLOWED_CATEGORY_CAR_EMERGENCY)
+ return State.ALLOW_CATEGORY_CAR_EMERGENCY
+ }
+
+ if (entry.sbn.notification.category == CATEGORY_CAR_WARNING) {
+ uiEventLogger.log(AvalancheEvent.AVALANCHE_SUPPRESSOR_HUN_ALLOWED_CATEGORY_CAR_WARNING)
+ return State.ALLOW_CATEGORY_CAR_WARNING
+ }
+
if (entry.sbn.notification.category == CATEGORY_EVENT) {
uiEventLogger.log(AvalancheEvent.AVALANCHE_SUPPRESSOR_HUN_ALLOWED_CATEGORY_EVENT)
return State.ALLOW_CATEGORY_EVENT
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 06af980..9d13a17 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -102,6 +102,7 @@
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation;
+import com.android.systemui.statusbar.notification.row.shared.LockscreenOtpRedaction;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationCompactMessagingTemplateViewWrapper;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
import com.android.systemui.statusbar.notification.shared.NotificationContentAlphaOptimization;
@@ -997,6 +998,9 @@
}
mNotificationParent = isChildInGroup ? parent : null;
mPrivateLayout.setIsChildInGroup(isChildInGroup);
+ if (LockscreenOtpRedaction.isEnabled()) {
+ mPublicLayout.setIsChildInGroup(isChildInGroup);
+ }
updateBackgroundForGroupState();
updateClickAndFocus();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HeadsUpStyleProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HeadsUpStyleProvider.kt
index 9d0fcd3..245b267 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HeadsUpStyleProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HeadsUpStyleProvider.kt
@@ -19,6 +19,7 @@
import android.app.Flags
import android.os.SystemProperties
import com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryStore
+import com.android.systemui.util.Compile
import javax.inject.Inject
/**
@@ -43,5 +44,6 @@
/** developer setting to always show Minimal HUN, even if the device is not in full screen */
private fun alwaysShow() =
- SystemProperties.getBoolean("persist.compact_heads_up_notification.always_show", false)
+ Compile.IS_DEBUG &&
+ SystemProperties.getBoolean("persist.compact_heads_up_notification.always_show", false)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
index ba1cfcc..0738a03 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
@@ -46,7 +46,7 @@
import java.util.Objects;
/**
- * A hybrid view which may contain information about one ore more conversations.
+ * A hybrid view which may contain information about one or more conversations.
*/
public class HybridConversationNotificationView extends HybridNotificationView {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index af5117e..8c80fd4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -56,8 +56,8 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation;
import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation;
+import com.android.systemui.statusbar.notification.row.shared.LockscreenOtpRedaction;
import com.android.systemui.statusbar.notification.row.shared.NotificationRowContentBinderRefactor;
-import com.android.systemui.statusbar.notification.row.ui.viewbinder.SingleLineConversationViewBinder;
import com.android.systemui.statusbar.notification.row.ui.viewbinder.SingleLineViewBinder;
import com.android.systemui.statusbar.notification.row.ui.viewmodel.SingleLineViewModel;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
@@ -196,8 +196,8 @@
result = inflateSmartReplyViews(result, reInflateFlags, entry, row.getContext(),
packageContext, row.getExistingSmartReplyState(), smartRepliesInflater, mLogger);
+ boolean isConversation = entry.getRanking().isConversation();
if (AsyncHybridViewInflation.isEnabled()) {
- boolean isConversation = entry.getRanking().isConversation();
Notification.MessagingStyle messagingStyle = null;
if (isConversation) {
messagingStyle = mConversationProcessor
@@ -210,8 +210,22 @@
builder,
row.getContext()
);
- result.mInflatedSingleLineViewHolder =
- SingleLineViewInflater.inflateSingleLineViewHolder(
+ result.mInflatedSingleLineView =
+ SingleLineViewInflater.inflatePrivateSingleLineView(
+ isConversation,
+ reInflateFlags,
+ entry,
+ row.getContext(),
+ mLogger
+ );
+ }
+
+ if (LockscreenOtpRedaction.isEnabled()) {
+ result.mPublicInflatedSingleLineViewModel =
+ SingleLineViewInflater.inflateRedactedSingleLineViewModel(row.getContext(),
+ isConversation);
+ result.mPublicInflatedSingleLineView =
+ SingleLineViewInflater.inflatePublicSingleLineView(
isConversation,
reInflateFlags,
entry,
@@ -291,6 +305,16 @@
row.getPrivateLayout().setHeadsUpInflatedSmartReplies(null);
});
break;
+ case FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE:
+ if (LockscreenOtpRedaction.isEnabled()) {
+ row.getPublicLayout()
+ .performWhenContentInactive(VISIBLE_TYPE_SINGLELINE, () -> {
+ row.getPublicLayout().setSingleLineView(null);
+ mRemoteViewCache.removeCachedView(entry,
+ FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE);
+ });
+ }
+ break;
case FLAG_CONTENT_VIEW_PUBLIC:
row.getPublicLayout().performWhenContentInactive(VISIBLE_TYPE_CONTRACTED, () -> {
row.getPublicLayout().setContractedChild(null);
@@ -334,6 +358,10 @@
row.getPublicLayout().removeContentInactiveRunnable(VISIBLE_TYPE_CONTRACTED);
}
if (AsyncHybridViewInflation.isEnabled()
+ && (contentViews & FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE) != 0) {
+ row.getPublicLayout().removeContentInactiveRunnable(VISIBLE_TYPE_SINGLELINE);
+ }
+ if (LockscreenOtpRedaction.isEnabled()
&& (contentViews & FLAG_CONTENT_VIEW_SINGLE_LINE) != 0) {
row.getPrivateLayout().removeContentInactiveRunnable(VISIBLE_TYPE_SINGLELINE);
}
@@ -935,19 +963,21 @@
if (AsyncHybridViewInflation.isEnabled()
&& (reInflateFlags & FLAG_CONTENT_VIEW_SINGLE_LINE) != 0) {
- HybridNotificationView viewHolder = result.mInflatedSingleLineViewHolder;
+ HybridNotificationView view = result.mInflatedSingleLineView;
SingleLineViewModel viewModel = result.mInflatedSingleLineViewModel;
- if (viewHolder != null && viewModel != null) {
- if (viewModel.isConversation()) {
- SingleLineConversationViewBinder.bind(
- result.mInflatedSingleLineViewModel,
- result.mInflatedSingleLineViewHolder
- );
- } else {
- SingleLineViewBinder.bind(result.mInflatedSingleLineViewModel,
- result.mInflatedSingleLineViewHolder);
- }
- privateLayout.setSingleLineView(result.mInflatedSingleLineViewHolder);
+ if (view != null && viewModel != null) {
+ SingleLineViewBinder.bind(viewModel, view);
+ privateLayout.setSingleLineView(result.mInflatedSingleLineView);
+ }
+ }
+
+ if (LockscreenOtpRedaction.isEnabled()
+ && (reInflateFlags & FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE) != 0) {
+ HybridNotificationView view = result.mPublicInflatedSingleLineView;
+ SingleLineViewModel viewModel = result.mPublicInflatedSingleLineViewModel;
+ if (view != null && viewModel != null) {
+ SingleLineViewBinder.bind(viewModel, view);
+ publicLayout.setSingleLineView(result.mPublicInflatedSingleLineView);
}
}
@@ -1211,8 +1241,22 @@
recoveredBuilder,
mContext
);
- result.mInflatedSingleLineViewHolder =
- SingleLineViewInflater.inflateSingleLineViewHolder(
+ result.mInflatedSingleLineView =
+ SingleLineViewInflater.inflatePrivateSingleLineView(
+ isConversation,
+ mReInflateFlags,
+ mEntry,
+ mContext,
+ mLogger
+ );
+ }
+
+ if (LockscreenOtpRedaction.isEnabled()) {
+ result.mPublicInflatedSingleLineViewModel =
+ SingleLineViewInflater.inflateRedactedSingleLineViewModel(mContext,
+ isConversation);
+ result.mPublicInflatedSingleLineView =
+ SingleLineViewInflater.inflatePublicSingleLineView(
isConversation,
mReInflateFlags,
mEntry,
@@ -1347,8 +1391,13 @@
// ViewModel for SingleLineView, holds the UI State
SingleLineViewModel mInflatedSingleLineViewModel;
+ // ViewModel for public SingleLineView, holds the UI State
+ SingleLineViewModel mPublicInflatedSingleLineViewModel;
// Inflated SingleLineViewHolder, SingleLineView that lacks the UI State
- HybridNotificationView mInflatedSingleLineViewHolder;
+ HybridNotificationView mInflatedSingleLineView;
+ // Inflated SingleLineViewHolder, SingleLineView that lacks the UI State for the public
+ // single line view
+ HybridNotificationView mPublicInflatedSingleLineView;
}
@VisibleForTesting
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 3f46902..7119145 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
@@ -113,7 +113,8 @@
private View mContractedChild;
private View mExpandedChild;
private View mHeadsUpChild;
- private HybridNotificationView mSingleLineView;
+ @VisibleForTesting
+ protected HybridNotificationView mSingleLineView;
@Nullable public DisposableHandle mContractedBinderHandle;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java
index fe0ee52..07384af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java
@@ -89,6 +89,7 @@
FLAG_CONTENT_VIEW_SINGLE_LINE,
FLAG_GROUP_SUMMARY_HEADER,
FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER,
+ FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE,
FLAG_CONTENT_VIEW_ALL})
@interface InflationFlag {}
/**
@@ -105,7 +106,7 @@
*/
int FLAG_CONTENT_VIEW_HEADS_UP = 1 << 2;
/**
- * The public view. This is a version of the contracted view that hides sensitive
+ * The public view. This is a version of the contracted view that hides sensitive
* information and is used on the lock screen if we determine that the notification's
* content should be hidden.
*/
@@ -126,7 +127,14 @@
*/
int FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER = 1 << 6;
- int FLAG_CONTENT_VIEW_ALL = (1 << 7) - 1;
+ /**
+ * The public single line view. This is a version of the contracted view that hides sensitive
+ * information and is used on the lock screen if we determine that the notification's
+ * content should be hidden, and the notification is shown as a child in a group.
+ */
+ int FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE = 1 << 7;
+
+ int FLAG_CONTENT_VIEW_ALL = (1 << 8) - 1;
/**
* Parameters for content view binding
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt
index 492d802..a5cd2a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt
@@ -55,6 +55,7 @@
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_SINGLE_LINE
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_GROUP_SUMMARY_HEADER
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER
@@ -63,11 +64,11 @@
import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation
import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation
import com.android.systemui.statusbar.notification.row.shared.HeadsUpStatusBarModel
+import com.android.systemui.statusbar.notification.row.shared.LockscreenOtpRedaction
import com.android.systemui.statusbar.notification.row.shared.NewRemoteViews
import com.android.systemui.statusbar.notification.row.shared.NotificationContentModel
import com.android.systemui.statusbar.notification.row.shared.NotificationRowContentBinderRefactor
import com.android.systemui.statusbar.notification.row.shared.RichOngoingContentModel
-import com.android.systemui.statusbar.notification.row.ui.viewbinder.SingleLineConversationViewBinder
import com.android.systemui.statusbar.notification.row.ui.viewbinder.SingleLineViewBinder
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer
@@ -202,7 +203,19 @@
if (AsyncHybridViewInflation.isEnabled) {
result.inflatedSingleLineView =
result.contentModel.singleLineViewModel?.let { viewModel ->
- SingleLineViewInflater.inflateSingleLineViewHolder(
+ SingleLineViewInflater.inflatePrivateSingleLineView(
+ viewModel.isConversation(),
+ reInflateFlags,
+ entry,
+ systemUIContext,
+ logger,
+ )
+ }
+ }
+ if (LockscreenOtpRedaction.isEnabled) {
+ result.inflatedPublicSingleLineView =
+ result.contentModel.publicSingleLineViewModel?.let { viewModel ->
+ SingleLineViewInflater.inflatePublicSingleLineView(
viewModel.isConversation(),
reInflateFlags,
entry,
@@ -294,6 +307,13 @@
}
}
}
+ FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE -> {
+ if (LockscreenOtpRedaction.isEnabled) {
+ row.publicLayout.performWhenContentInactive(VISIBLE_TYPE_SINGLELINE) {
+ row.publicLayout.setSingleLineView(null)
+ }
+ }
+ }
else -> {}
}
}
@@ -327,6 +347,12 @@
) {
row.privateLayout.removeContentInactiveRunnable(VISIBLE_TYPE_SINGLELINE)
}
+ if (
+ LockscreenOtpRedaction.isEnabled &&
+ contentViews and FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE != 0
+ ) {
+ row.publicLayout.removeContentInactiveRunnable(VISIBLE_TYPE_SINGLELINE)
+ }
}
/**
@@ -449,7 +475,7 @@
logger.logAsyncTaskProgress(entry, "inflating single line view")
inflationProgress.inflatedSingleLineView =
inflationProgress.contentModel.singleLineViewModel?.let {
- SingleLineViewInflater.inflateSingleLineViewHolder(
+ SingleLineViewInflater.inflatePrivateSingleLineView(
it.isConversation(),
reInflateFlags,
entry,
@@ -459,6 +485,20 @@
}
}
+ if (LockscreenOtpRedaction.isEnabled) {
+ logger.logAsyncTaskProgress(entry, "inflating public single line view")
+ inflationProgress.inflatedPublicSingleLineView =
+ inflationProgress.contentModel.publicSingleLineViewModel?.let { viewModel ->
+ SingleLineViewInflater.inflatePublicSingleLineView(
+ viewModel.isConversation(),
+ reInflateFlags,
+ entry,
+ context,
+ logger
+ )
+ }
+ }
+
if (reInflateFlags and CONTENT_VIEWS_TO_CREATE_RICH_ONGOING != 0) {
logger.logAsyncTaskProgress(entry, "inflating RON view")
inflationProgress.richOngoingNotificationViewHolder =
@@ -582,6 +622,8 @@
// Inflated SingleLineView that lacks the UI State
var inflatedSingleLineView: HybridNotificationView? = null
+ // Inflated public SingleLineView that lacks the UI State
+ var inflatedPublicSingleLineView: HybridNotificationView? = null
}
@VisibleForTesting
@@ -706,6 +748,18 @@
)
} else null
+ val publicSingleLineViewModel =
+ if (
+ LockscreenOtpRedaction.isEnabled &&
+ reInflateFlags and FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE != 0
+ ) {
+ logger.logAsyncTaskProgress(entry, "inflating public single line view model")
+ SingleLineViewInflater.inflateRedactedSingleLineViewModel(
+ systemUIContext,
+ entry.ranking.isConversation
+ )
+ } else null
+
val headsUpStatusBarModel =
HeadsUpStatusBarModel(
privateText = builder.getHeadsUpStatusBarText(/* publicMode= */ false),
@@ -716,6 +770,7 @@
NotificationContentModel(
headsUpStatusBarModel = headsUpStatusBarModel,
singleLineViewModel = singleLineViewModel,
+ publicSingleLineViewModel = publicSingleLineViewModel,
richOngoingContentModel = richOngoingContentModel,
)
@@ -1405,15 +1460,23 @@
val singleLineView = result.inflatedSingleLineView
val viewModel = result.contentModel.singleLineViewModel
if (singleLineView != null && viewModel != null) {
- if (viewModel.isConversation()) {
- SingleLineConversationViewBinder.bind(viewModel, singleLineView)
- } else {
- SingleLineViewBinder.bind(viewModel, singleLineView)
- }
+ SingleLineViewBinder.bind(viewModel, singleLineView)
row.privateLayout.setSingleLineView(result.inflatedSingleLineView)
}
}
+ if (
+ LockscreenOtpRedaction.isEnabled &&
+ reInflateFlags and FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE != 0
+ ) {
+ val singleLineView = result.inflatedPublicSingleLineView
+ val viewModel = result.contentModel.publicSingleLineViewModel
+ if (singleLineView != null && viewModel != null) {
+ SingleLineViewBinder.bind(viewModel, singleLineView)
+ row.publicLayout.setSingleLineView(result.inflatedPublicSingleLineView)
+ }
+ }
+
// after updating the content model, set the view, then start the new binder
result.richOngoingNotificationViewHolder?.let { viewHolder ->
row.privateLayout.contractedChild = viewHolder.view
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
index 463192c..d67947d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
@@ -30,6 +30,7 @@
import com.android.internal.widget.PeopleHelper
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.logKey
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_SINGLE_LINE
import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation
import com.android.systemui.statusbar.notification.row.ui.viewmodel.ConversationAvatar
@@ -107,6 +108,36 @@
)
}
+ @JvmStatic
+ fun inflateRedactedSingleLineViewModel(
+ context: Context,
+ isConversation: Boolean = false
+ ): SingleLineViewModel {
+ val conversationData =
+ if (isConversation) {
+ ConversationData(
+ null,
+ SingleIcon(
+ context.getDrawable(
+ com.android.systemui.res.R.drawable
+ .ic_redacted_notification_single_line_icon
+ )
+ )
+ )
+ } else {
+ null
+ }
+ return SingleLineViewModel(
+ context.getString(
+ com.android.systemui.res.R.string.redacted_notification_single_line_title
+ ),
+ context.getString(
+ com.android.systemui.res.R.string.redacted_notification_single_line_text
+ ),
+ conversationData
+ )
+ }
+
/** load conversation text data from the MessagingStyle of conversation notifications */
private fun MessagingStyle.loadConversationTextData(
systemUiContext: Context
@@ -137,8 +168,8 @@
// We need to find back-up values for those texts if they are needed and empty
return ConversationTextData(
- conversationTitle = conversationTitle
- ?: findBackUpConversationTitle(senderName, systemUiContext),
+ conversationTitle =
+ conversationTitle ?: findBackUpConversationTitle(senderName, systemUiContext),
conversationText = conversationText,
senderName = senderName,
)
@@ -328,12 +359,27 @@
return FacePile(
topIconDrawable = secondLastIcon.loadDrawable(systemUiContext),
bottomIconDrawable = lastIcon.loadDrawable(systemUiContext),
- bottomBackgroundColor = builder.getBackgroundColor(/* isHeader = */ false),
+ bottomBackgroundColor = builder.getBackgroundColor(/* isHeader= */ false),
)
}
@JvmStatic
- fun inflateSingleLineViewHolder(
+ fun inflatePublicSingleLineView(
+ isConversation: Boolean,
+ reinflateFlags: Int,
+ entry: NotificationEntry,
+ context: Context,
+ logger: NotificationRowContentBinderLogger,
+ ): HybridNotificationView? {
+ return if ((reinflateFlags and FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE) == 0) {
+ null
+ } else {
+ inflateSingleLineView(isConversation, reinflateFlags, entry, context, logger)
+ }
+ }
+
+ @JvmStatic
+ fun inflatePrivateSingleLineView(
isConversation: Boolean,
reinflateFlags: Int,
entry: NotificationEntry,
@@ -341,9 +387,21 @@
logger: NotificationRowContentBinderLogger,
): HybridNotificationView? {
if (AsyncHybridViewInflation.isUnexpectedlyInLegacyMode()) return null
- if (reinflateFlags and FLAG_CONTENT_VIEW_SINGLE_LINE == 0) {
- return null
+ return if ((reinflateFlags and FLAG_CONTENT_VIEW_SINGLE_LINE) == 0) {
+ null
+ } else {
+ inflateSingleLineView(isConversation, reinflateFlags, entry, context, logger)
}
+ }
+
+ private fun inflateSingleLineView(
+ isConversation: Boolean,
+ reinflateFlags: Int,
+ entry: NotificationEntry,
+ context: Context,
+ logger: NotificationRowContentBinderLogger,
+ ): HybridNotificationView? {
+ if (AsyncHybridViewInflation.isUnexpectedlyInLegacyMode()) return null
logger.logInflateSingleLine(entry, reinflateFlags, isConversation)
logger.logAsyncTaskProgress(entry, "inflating single-line content view")
@@ -356,7 +414,7 @@
if (isConversation)
com.android.systemui.res.R.layout.hybrid_conversation_notification
else com.android.systemui.res.R.layout.hybrid_notification
- view = inflater.inflate(layoutRes, /* root = */ null) as HybridNotificationView
+ view = inflater.inflate(layoutRes, /* root= */ null) as HybridNotificationView
if (view == null) {
Log.wtf(TAG, "Single-line view inflation result is null for entry: ${entry.logKey}")
}
@@ -368,7 +426,7 @@
name: CharSequence?,
uniqueNames: PeopleHelper.NameToPrefixMap? = null
): Icon {
- val layoutColor = getSmallIconColor(/* isHeader = */ false)
+ val layoutColor = getSmallIconColor(/* isHeader= */ false)
if (!name.isNullOrEmpty()) {
val symbol = uniqueNames?.getPrefix(name) ?: ""
return peopleHelper.createAvatarSymbol(
@@ -379,7 +437,7 @@
}
// If name is null, create default avatar with background color
// TODO(b/319829062): Investigate caching default icon for color
- return peopleHelper.createAvatarSymbol(/* name = */ "", /* symbol = */ "", layoutColor)
+ return peopleHelper.createAvatarSymbol(/* name= */ "", /* symbol= */ "", layoutColor)
}
private fun Person.getKeyOrName(): CharSequence? = if (key == null) name else key
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/LockscreenOtpRedaction.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/LockscreenOtpRedaction.kt
new file mode 100644
index 0000000..078deb9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/LockscreenOtpRedaction.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.row.shared
+
+import android.app.Flags
+import android.app.Flags.redactSensitiveContentNotificationsOnLockscreen
+import com.android.systemui.flags.FlagToken
+
+/** Helper for reading or using the async hybrid view inflation flag state. */
+object LockscreenOtpRedaction {
+ const val FLAG_NAME = Flags.FLAG_REDACT_SENSITIVE_CONTENT_NOTIFICATIONS_ON_LOCKSCREEN
+
+ /** A token used for dependency declaration */
+ val token: FlagToken
+ get() = FlagToken(FLAG_NAME, isEnabled)
+
+ @JvmStatic
+ inline val isEnabled
+ get() =
+ redactSensitiveContentNotificationsOnLockscreen() && AsyncHybridViewInflation.isEnabled
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/NotificationContentModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/NotificationContentModel.kt
index 46010a1..0f9a5a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/NotificationContentModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/NotificationContentModel.kt
@@ -21,6 +21,7 @@
data class NotificationContentModel(
val headsUpStatusBarModel: HeadsUpStatusBarModel,
val singleLineViewModel: SingleLineViewModel? = null,
+ val publicSingleLineViewModel: SingleLineViewModel? = null,
val richOngoingContentModel: RichOngoingContentModel? = null,
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineConversationViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineConversationViewBinder.kt
deleted file mode 100644
index 69284bd..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineConversationViewBinder.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.row.ui.viewbinder
-
-import com.android.systemui.statusbar.notification.row.HybridConversationNotificationView
-import com.android.systemui.statusbar.notification.row.HybridNotificationView
-import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation
-import com.android.systemui.statusbar.notification.row.ui.viewmodel.SingleLineViewModel
-
-object SingleLineConversationViewBinder {
- @JvmStatic
- fun bind(viewModel: SingleLineViewModel, view: HybridNotificationView?) {
- if (AsyncHybridViewInflation.isUnexpectedlyInLegacyMode()) return
- if (view !is HybridConversationNotificationView || !viewModel.isConversation()) {
- SingleLineViewBinder.bind(viewModel, view)
- return
- }
-
- viewModel.conversationData?.avatar?.let { view.setAvatar(it) }
- view.setText(
- viewModel.titleText,
- viewModel.contentText,
- viewModel.conversationData?.conversationSenderName
- )
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt
index 22e10c1..3b0f1ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt
@@ -16,19 +16,32 @@
package com.android.systemui.statusbar.notification.row.ui.viewbinder
+import com.android.systemui.statusbar.notification.row.HybridConversationNotificationView
import com.android.systemui.statusbar.notification.row.HybridNotificationView
+import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation
import com.android.systemui.statusbar.notification.row.ui.viewmodel.SingleLineViewModel
object SingleLineViewBinder {
@JvmStatic
fun bind(viewModel: SingleLineViewModel?, view: HybridNotificationView?) {
- // bind the title and content text views
- view?.apply {
- bind(
- /* title = */ viewModel?.titleText,
- /* text = */ viewModel?.contentText,
- /* contentView = */ null
+ if (viewModel?.isConversation() == true && view is HybridConversationNotificationView) {
+ if (AsyncHybridViewInflation.isUnexpectedlyInLegacyMode()) return
+
+ viewModel.conversationData?.avatar?.let { view.setAvatar(it) }
+ view.setText(
+ viewModel.titleText,
+ viewModel.contentText,
+ viewModel.conversationData?.conversationSenderName
)
+ } else {
+ // bind the title and content text views
+ view?.apply {
+ bind(
+ /* title = */ viewModel?.titleText,
+ /* text = */ viewModel?.contentText,
+ /* contentView = */ null
+ )
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/ActiveNotificationModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/ActiveNotificationModel.kt
index 5527efc..cf19938 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/ActiveNotificationModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/ActiveNotificationModel.kt
@@ -15,7 +15,9 @@
package com.android.systemui.statusbar.notification.shared
+import android.app.PendingIntent
import android.graphics.drawable.Icon
+import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.notification.stack.PriorityBucket
/**
@@ -32,6 +34,8 @@
val key: String,
/** Notification group key associated with this entry. */
val groupKey: String?,
+ /** When this notification was posted. */
+ val whenTime: Long,
/** Is this entry in the ambient / minimized section (lowest priority)? */
val isAmbient: Boolean,
/**
@@ -56,16 +60,22 @@
val shelfIcon: Icon?,
/** Icon to display in the status bar. */
val statusBarIcon: Icon?,
+ /** Icon to display in the status bar chip. */
+ val statusBarChipIconView: StatusBarIconView?,
/** The notifying app's [packageName]'s uid. */
val uid: Int,
/** The notifying app's packageName. */
val packageName: String,
+ /** The intent to execute if UI related to this notification is clicked. */
+ val contentIntent: PendingIntent?,
/** A small per-notification ID, used for statsd logging. */
val instanceId: Int?,
/** If this notification is the group summary for a group of notifications. */
val isGroupSummary: Boolean,
/** Indicates in which section the notification is displayed in. @see [PriorityBucket]. */
@PriorityBucket val bucket: Int,
+ /** The call type set on the notification. */
+ val callType: CallType,
) : ActiveNotificationEntryModel()
/** Model for a group of notifications. */
@@ -74,3 +84,17 @@
val summary: ActiveNotificationModel,
val children: List<ActiveNotificationModel>,
) : ActiveNotificationEntryModel()
+
+/** Specifies the call type set on the notification. For most notifications, will be [None]. */
+enum class CallType {
+ /** This notification isn't a call-type notification. */
+ None,
+ /** See [android.app.Notification.CallStyle.CALL_TYPE_INCOMING]. */
+ Incoming,
+ /** See [android.app.Notification.CallStyle.CALL_TYPE_ONGOING]. */
+ Ongoing,
+ /** See [android.app.Notification.CallStyle.CALL_TYPE_SCREENING]. */
+ Screening,
+ /** See [android.app.Notification.CallStyle.CALL_TYPE_UNKNOWN]. */
+ Unknown,
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/GroupHunAnimationFix.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/GroupHunAnimationFix.kt
index 3b30c86..1dac8b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/GroupHunAnimationFix.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/GroupHunAnimationFix.kt
@@ -20,10 +20,13 @@
import com.android.systemui.flags.FlagToken
import com.android.systemui.flags.RefactorFlagUtils
-/** Helper for com.android.systemui.Flags.FLAG_NOTIFICATION_GROUP_HUN_REMOVAL_ANIMATION_FIX */
+/**
+ * Helper for com.android.systemui.Flags.FLAG_NOTIFICATION_GROUP_HUN_REMOVAL_ANIMATION_FIX, which
+ * now uses FLAG_NOTIFICATION_AVALANCHE_THROTTLE_HUN
+ */
@Suppress("NOTHING_TO_INLINE")
object GroupHunAnimationFix {
- const val FLAG_NAME = Flags.FLAG_NOTIFICATION_GROUP_HUN_REMOVAL_ANIMATION_FIX
+ const val FLAG_NAME = Flags.FLAG_NOTIFICATION_AVALANCHE_THROTTLE_HUN
/** A token used for dependency declaration */
val token: FlagToken
@@ -32,7 +35,7 @@
/** Return whether the fix is enabled */
@JvmStatic
inline val isEnabled
- get() = Flags.notificationGroupHunRemovalAnimationFix()
+ get() = Flags.notificationAvalancheThrottleHun()
/**
* Called to ensure code is only run when the flag is enabled. This protects users from the
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 5d2b61b..20b1fff 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
@@ -89,8 +89,10 @@
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.qs.flags.QSComposeFragment;
import com.android.systemui.res.R;
import com.android.systemui.scene.shared.flag.SceneContainerFlag;
+import com.android.systemui.shade.QSHeaderBoundsProvider;
import com.android.systemui.shade.TouchLogger;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.NotificationShelf;
@@ -351,6 +353,10 @@
private final NotificationSection[] mSections;
private final ArrayList<ExpandableView> mTmpSortedChildren = new ArrayList<>();
protected ViewGroup mQsHeader;
+
+ @Nullable
+ private QSHeaderBoundsProvider mQSHeaderBoundsProvider;
+
// Rect of QsHeader. Kept as a field just to avoid creating a new one each time.
private final Rect mQsHeaderBound = new Rect();
private boolean mContinuousShadowUpdate;
@@ -1179,7 +1185,21 @@
if (!SceneContainerFlag.isEnabled()) {
// Give The Algorithm information regarding the QS height so it can layout notifications
// properly. Needed for some devices that grows notifications down-to-top
- mStackScrollAlgorithm.updateQSFrameTop(mQsHeader == null ? 0 : mQsHeader.getHeight());
+ int height;
+ if (QSComposeFragment.isEnabled()) {
+ if (mQSHeaderBoundsProvider != null) {
+ height = mQSHeaderBoundsProvider.getHeightProvider().invoke();
+ } else {
+ height = 0;
+ }
+ } else {
+ if (mQsHeader != null) {
+ height = mQsHeader.getHeight();
+ } else {
+ height = 0;
+ }
+ }
+ mStackScrollAlgorithm.updateQSFrameTop(height);
}
// Once the layout has finished, we don't need to animate any scrolling clampings anymore.
@@ -1544,12 +1564,7 @@
public void setExpandedHeight(float height) {
final boolean skipHeightUpdate = shouldSkipHeightUpdate();
- // when scene framework is enabled and in single shade, updateStackPosition is already
- // called by updateTopPadding every time the stack moves, so skip it here to avoid
- // flickering.
- if (!SceneContainerFlag.isEnabled() || mShouldUseSplitNotificationShade) {
- updateStackPosition();
- }
+ updateStackPosition();
if (!skipHeightUpdate) {
mExpandedHeight = height;
@@ -1829,10 +1844,16 @@
}
public void setQsHeader(ViewGroup qsHeader) {
- SceneContainerFlag.assertInLegacyMode();
+ QSComposeFragment.assertInLegacyMode();
mQsHeader = qsHeader;
}
+ public void setQsHeaderBoundsProvider(QSHeaderBoundsProvider qsHeaderBoundsProvider) {
+ SceneContainerFlag.assertInLegacyMode();
+ QSComposeFragment.isUnexpectedlyInLegacyMode();
+ mQSHeaderBoundsProvider = qsHeaderBoundsProvider;
+ }
+
public static boolean isPinnedHeadsUp(View v) {
if (v instanceof ExpandableNotificationRow row) {
return row.isHeadsUp() && row.isPinned();
@@ -3750,7 +3771,20 @@
return ev.getY() < mAmbientState.getStackTop();
}
- mQsHeader.getBoundsOnScreen(mQsHeaderBound);
+ if (QSComposeFragment.isEnabled()) {
+ if (mQSHeaderBoundsProvider == null) {
+ return false;
+ } else {
+ mQSHeaderBoundsProvider.getBoundsOnScreenProvider().invoke(mQsHeaderBound);
+ }
+ } else {
+ if (mQsHeader == null) {
+ return false;
+ } else {
+ mQsHeader.getBoundsOnScreen(mQsHeaderBound);
+ }
+ }
+
/**
* One-handed mode defines a feature FEATURE_ONE_HANDED of DisplayArea {@link DisplayArea}
* that will translate down the Y-coordinate whole window screen type except for
@@ -3760,7 +3794,10 @@
* of DisplayArea into relative coordinates for all windows, we need to correct the
* QS Head bounds here.
*/
- final int xOffset = Math.round(ev.getRawX() - ev.getX() + mQsHeader.getLeft());
+ int left =
+ QSComposeFragment.isEnabled() ? mQSHeaderBoundsProvider.getLeftProvider().invoke()
+ : mQsHeader.getLeft();
+ final int xOffset = Math.round(ev.getRawX() - ev.getX() + left);
final int yOffset = Math.round(ev.getRawY() - ev.getY());
mQsHeaderBound.offsetTo(xOffset, yOffset);
return mQsHeaderBound.contains((int) ev.getRawX(), (int) ev.getRawY());
@@ -3814,6 +3851,7 @@
}
void handleEmptySpaceClick(MotionEvent ev) {
+ if (SceneContainerFlag.isEnabled()) return;
logEmptySpaceClick(ev, isBelowLastNotification(mInitialTouchX, mInitialTouchY),
mStatusBarState, mTouchIsClick);
switch (ev.getActionMasked()) {
@@ -4025,6 +4063,7 @@
}
public void setOnEmptySpaceClickListener(OnEmptySpaceClickListener listener) {
+ SceneContainerFlag.assertInLegacyMode();
mOnEmptySpaceClickListener = listener;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index fb1c525..608fe95 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -80,9 +80,11 @@
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.power.domain.interactor.PowerInteractor;
+import com.android.systemui.qs.flags.QSComposeFragment;
import com.android.systemui.res.R;
import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.scene.ui.view.WindowRootView;
+import com.android.systemui.shade.QSHeaderBoundsProvider;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.shade.ShadeViewController;
import com.android.systemui.statusbar.CommandQueue;
@@ -1075,6 +1077,7 @@
public void setOnEmptySpaceClickListener(
OnEmptySpaceClickListener listener) {
+ SceneContainerFlag.assertInLegacyMode();
mView.setOnEmptySpaceClickListener(listener);
}
@@ -1522,9 +1525,15 @@
* Sets the QS header. Used to check if a touch is within its bounds.
*/
public void setQsHeader(ViewGroup view) {
+ QSComposeFragment.assertInLegacyMode();
mView.setQsHeader(view);
}
+ public void setQsHeaderBoundsProvider(QSHeaderBoundsProvider qsHeaderBoundsProvider) {
+ QSComposeFragment.isUnexpectedlyInLegacyMode();
+ mView.setQsHeaderBoundsProvider(qsHeaderBoundsProvider);
+ }
+
public void setAnimationsEnabled(boolean enabled) {
mView.setAnimationsEnabled(enabled);
}
@@ -1630,6 +1639,7 @@
}
public void setMaxTopPadding(int padding) {
+ SceneContainerFlag.assertInLegacyMode();
mView.setMaxTopPadding(padding);
}
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 b6de78e..3a3b05b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -30,7 +30,6 @@
import static com.android.systemui.Flags.keyboardShortcutHelperRewrite;
import static com.android.systemui.Flags.lightRevealMigration;
import static com.android.systemui.Flags.newAodTransition;
-import static com.android.systemui.Flags.truncatedStatusBarIconsFix;
import static com.android.systemui.charging.WirelessChargingAnimation.UNKNOWN_BATTERY_LEVEL;
import static com.android.systemui.flags.Flags.SHORTCUT_LIST_SEARCH_LAYOUT;
import static com.android.systemui.statusbar.NotificationLockscreenUserManager.PERMISSION_SELF;
@@ -913,8 +912,8 @@
result.mRequestedVisibleTypes, result.mPackageName, result.mLetterboxDetails);
// StatusBarManagerService has a back up of IME token and it's restored here.
- mCommandQueueCallbacks.setImeWindowStatus(mDisplayId, result.mImeToken,
- result.mImeWindowVis, result.mImeBackDisposition, result.mShowImeSwitcher);
+ mCommandQueueCallbacks.setImeWindowStatus(mDisplayId, result.mImeWindowVis,
+ result.mImeBackDisposition, result.mShowImeSwitcher);
// Set up the initial icon state
int numIcons = result.mIcons.size();
@@ -1933,11 +1932,6 @@
mQSPanelController.updateResources();
}
- if (!truncatedStatusBarIconsFix()) {
- if (mStatusBarWindowController != null) {
- mStatusBarWindowController.refreshStatusBarHeight();
- }
- }
if (mShadeSurface != null) {
mShadeSurface.updateResources();
}
@@ -2995,7 +2989,7 @@
@Override
public void onFalse() {
// Hides quick settings, bouncer, and quick-quick settings.
- mStatusBarKeyguardViewManager.reset(true, /* isFalsingReset= */true);
+ mStatusBarKeyguardViewManager.reset(true);
}
};
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 a32d5fe..ca1fb78b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
@@ -437,6 +437,13 @@
mNotificationShadeWindowController.setDozeScreenBrightness(brightness);
}
+
+ @Override
+ public void setDozeScreenBrightnessFloat(float brightness) {
+ mDozeLog.traceDozeScreenBrightnessFloat(brightness);
+ mNotificationShadeWindowController.setDozeScreenBrightnessFloat(brightness);
+ }
+
@Override
public void setAodDimmingScrim(float scrimOpacity) {
mDozeLog.traceSetAodDimmingScrim(scrimOpacity);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/OWNERS b/packages/SystemUI/src/com/android/systemui/statusbar/phone/OWNERS
index 4657e9b..92a333e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/OWNERS
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/OWNERS
@@ -1,6 +1,6 @@
per-file *Notification* = set noparent
per-file *Notification* = file:../notification/OWNERS
-per-file NotificationIcon* = ccassidy@google.com, evanlaird@google.com, pixel@google.com
+per-file NotificationIcon* = file:../OWNERS
per-file NotificationShadeWindowControllerImpl.java = dupin@google.com, cinek@google.com, beverlyt@google.com, pixel@google.com, juliacr@google.com
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 6b47ac1..8115c36 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.phone;
-import static com.android.systemui.Flags.truncatedStatusBarIconsFix;
import android.annotation.Nullable;
import android.content.Context;
@@ -108,9 +107,7 @@
Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mClock);
if (updateDisplayParameters()) {
updateLayoutForCutout();
- if (truncatedStatusBarIconsFix()) {
- updateWindowHeight();
- }
+ updateWindowHeight();
}
}
@@ -135,9 +132,7 @@
updateLayoutForCutout();
requestLayout();
}
- if (truncatedStatusBarIconsFix()) {
- updateWindowHeight();
- }
+ updateWindowHeight();
}
void onDensityOrFontScaleChanged() {
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 88a2b23..2d775b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -708,7 +708,7 @@
* Shows the notification keyguard or the bouncer depending on
* {@link #needsFullscreenBouncer()}.
*/
- protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing, boolean isFalsingReset) {
+ protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) {
boolean isDozing = mDozing;
if (Flags.simPinRaceConditionOnRestart()) {
KeyguardState toState = mKeyguardTransitionInteractor.getTransitionState().getValue()
@@ -734,12 +734,8 @@
mPrimaryBouncerInteractor.show(/* isScrimmed= */ true);
}
}
- } else if (!isFalsingReset) {
- // Falsing resets can cause this to flicker, so don't reset in this case
- Log.i(TAG, "Sim bouncer is already showing, issuing a refresh");
- mPrimaryBouncerInteractor.hide();
- mPrimaryBouncerInteractor.show(/* isScrimmed= */ true);
-
+ } else {
+ Log.e(TAG, "Attempted to show the sim bouncer when it is already showing.");
}
} else {
mCentralSurfaces.showKeyguard();
@@ -961,10 +957,6 @@
@Override
public void reset(boolean hideBouncerWhenShowing) {
- reset(hideBouncerWhenShowing, /* isFalsingReset= */false);
- }
-
- public void reset(boolean hideBouncerWhenShowing, boolean isFalsingReset) {
if (mKeyguardStateController.isShowing() && !bouncerIsAnimatingAway()) {
final boolean isOccluded = mKeyguardStateController.isOccluded();
// Hide quick settings.
@@ -976,7 +968,7 @@
hideBouncer(false /* destroyView */);
}
} else {
- showBouncerOrKeyguard(hideBouncerWhenShowing, isFalsingReset);
+ showBouncerOrKeyguard(hideBouncerWhenShowing);
}
if (hideBouncerWhenShowing) {
hideAlternateBouncer(true);
@@ -1114,7 +1106,9 @@
SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__OCCLUDED);
if (mCentralSurfaces.isLaunchingActivityOverLockscreen()) {
final Runnable postCollapseAction = () -> {
- mNotificationShadeWindowController.setKeyguardOccluded(isOccluded);
+ if (!Flags.useTransitionsForKeyguardOccluded()) {
+ mNotificationShadeWindowController.setKeyguardOccluded(isOccluded);
+ }
reset(true /* hideBouncerWhenShowing */);
};
if (mCentralSurfaces.isDismissingShadeForActivityLaunch()) {
@@ -1130,7 +1124,9 @@
SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED,
SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN);
}
- mNotificationShadeWindowController.setKeyguardOccluded(isOccluded);
+ if (!Flags.useTransitionsForKeyguardOccluded()) {
+ mNotificationShadeWindowController.setKeyguardOccluded(isOccluded);
+ }
// setDozing(false) will call reset once we stop dozing. Also, if we're going away, there's
// no need to reset the keyguard views as we'll be gone shortly. Resetting now could cause
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
index 3898088..4368239 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
@@ -38,6 +38,7 @@
import com.android.systemui.log.core.LogLevel
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.res.R
+import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.chips.ui.view.ChipChronometer
import com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryStore
@@ -45,6 +46,9 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
+import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
+import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
+import com.android.systemui.statusbar.notification.shared.CallType
import com.android.systemui.statusbar.phone.ongoingcall.data.repository.OngoingCallRepository
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel
import com.android.systemui.statusbar.policy.CallbackController
@@ -65,6 +69,7 @@
private val context: Context,
private val ongoingCallRepository: OngoingCallRepository,
private val notifCollection: CommonNotifCollection,
+ private val activeNotificationsInteractor: ActiveNotificationsInteractor,
private val systemClock: SystemClock,
private val activityStarter: ActivityStarter,
@Main private val mainExecutor: Executor,
@@ -97,6 +102,7 @@
}
override fun onEntryUpdated(entry: NotificationEntry) {
+ StatusBarUseReposForCallChip.assertInLegacyMode()
// We have a new call notification or our existing call notification has been
// updated.
// TODO(b/183229367): This likely won't work if you take a call from one app then
@@ -109,6 +115,9 @@
CallNotificationInfo(
entry.sbn.key,
entry.sbn.notification.getWhen(),
+ // In this old listener pattern, we don't have access to the
+ // notification icon.
+ notificationIconView = null,
entry.sbn.notification.contentIntent,
entry.sbn.uid,
entry.sbn.notification.extras.getInt(
@@ -157,7 +166,25 @@
override fun start() {
dumpManager.registerDumpable(this)
- notifCollection.addCollectionListener(notifListener)
+
+ if (Flags.statusBarUseReposForCallChip()) {
+ scope.launch {
+ // Listening to [ActiveNotificationsInteractor] instead of using
+ // [NotifCollectionListener#onEntryUpdated] is better for two reasons:
+ // 1. ActiveNotificationsInteractor automatically filters the notification list to
+ // just notifications for the current user, which ensures we don't show a call chip
+ // for User 1's call while User 2 is active (see b/328584859).
+ // 2. ActiveNotificationsInteractor only emits notifications that are currently
+ // present in the shade, which means we know we've already inflated the icon that we
+ // might use for the call chip (see b/354930838).
+ activeNotificationsInteractor.ongoingCallNotification.collect {
+ updateInfoFromNotifModel(it)
+ }
+ }
+ } else {
+ notifCollection.addCollectionListener(notifListener)
+ }
+
scope.launch {
statusBarModeRepository.defaultDisplay.isInFullscreenMode.collect {
isFullscreen = it
@@ -200,8 +227,15 @@
callNotificationInfo
// This shouldn't happen, but protect against it in case
?: return OngoingCallModel.NoCall
+ val icon =
+ if (Flags.statusBarCallChipNotificationIcon()) {
+ currentInfo.notificationIconView
+ } else {
+ null
+ }
return OngoingCallModel.InCall(
startTimeMs = currentInfo.callStartTime,
+ notificationIconView = icon,
intent = currentInfo.intent,
)
} else {
@@ -221,6 +255,36 @@
synchronized(mListeners) { mListeners.remove(listener) }
}
+ private fun updateInfoFromNotifModel(notifModel: ActiveNotificationModel?) {
+ if (notifModel == null) {
+ removeChip()
+ } else if (notifModel.callType != CallType.Ongoing) {
+ logger.log(
+ TAG,
+ LogLevel.ERROR,
+ { str1 = notifModel.callType.name },
+ { "Notification Interactor sent ActiveNotificationModel with callType=$str1" },
+ )
+ removeChip()
+ } else {
+ val newOngoingCallInfo =
+ CallNotificationInfo(
+ notifModel.key,
+ notifModel.whenTime,
+ notifModel.statusBarChipIconView,
+ notifModel.contentIntent,
+ notifModel.uid,
+ isOngoing = true,
+ statusBarSwipedAway = callNotificationInfo?.statusBarSwipedAway ?: false
+ )
+ if (newOngoingCallInfo == callNotificationInfo) {
+ return
+ }
+ callNotificationInfo = newOngoingCallInfo
+ updateChip()
+ }
+ }
+
private fun updateChip() {
val currentCallNotificationInfo = callNotificationInfo ?: return
@@ -355,6 +419,8 @@
private data class CallNotificationInfo(
val key: String,
val callStartTime: Long,
+ /** The icon set as the [android.app.Notification.getSmallIcon] field. */
+ val notificationIconView: StatusBarIconView?,
val intent: PendingIntent?,
val uid: Int,
/** True if the call is currently ongoing (as opposed to incoming, screening, etc.). */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/StatusBarUseReposForCallChip.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/StatusBarUseReposForCallChip.kt
new file mode 100644
index 0000000..4bdd90e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/StatusBarUseReposForCallChip.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone.ongoingcall
+
+import com.android.systemui.Flags
+import com.android.systemui.flags.FlagToken
+import com.android.systemui.flags.RefactorFlagUtils
+
+/** Helper for reading or using the status bar use repos for call chip flag state. */
+@Suppress("NOTHING_TO_INLINE")
+object StatusBarUseReposForCallChip {
+ /** The aconfig flag name */
+ const val FLAG_NAME = Flags.FLAG_STATUS_BAR_USE_REPOS_FOR_CALL_CHIP
+
+ /** A token used for dependency declaration */
+ val token: FlagToken
+ get() = FlagToken(FLAG_NAME, isEnabled)
+
+ /** Is the refactor enabled */
+ @JvmStatic
+ inline val isEnabled
+ get() = Flags.statusBarUseReposForCallChip()
+
+ /**
+ * Called to ensure code is only run when the flag is enabled. This protects users from the
+ * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
+ * build to ensure that the refactor author catches issues in testing.
+ */
+ @JvmStatic
+ inline fun isUnexpectedlyInLegacyMode() =
+ RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME)
+
+ /**
+ * Called to ensure code is only run when the flag is disabled. This will throw an exception if
+ * the flag is enabled to ensure that the refactor author catches issues in testing.
+ */
+ @JvmStatic
+ inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/shared/model/OngoingCallModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/shared/model/OngoingCallModel.kt
index 2c48487..34bff80 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/shared/model/OngoingCallModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/shared/model/OngoingCallModel.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.phone.ongoingcall.shared.model
import android.app.PendingIntent
+import com.android.systemui.statusbar.StatusBarIconView
/** Represents the state of any ongoing calls. */
sealed interface OngoingCallModel {
@@ -31,7 +32,13 @@
* [com.android.systemui.util.time.SystemClock.currentTimeMillis], **not**
* [com.android.systemui.util.time.SystemClock.elapsedRealtime]. This value can be 0 if the
* user has started an outgoing call that hasn't been answered yet - see b/192379214.
+ * @property notificationIconView the [android.app.Notification.getSmallIcon] that's set on the
+ * call notification. We may use this icon in the chip instead of the default phone icon.
* @property intent the intent associated with the call notification.
*/
- data class InCall(val startTimeMs: Long, val intent: PendingIntent?) : OngoingCallModel
+ data class InCall(
+ val startTimeMs: Long,
+ val notificationIconView: StatusBarIconView?,
+ val intent: PendingIntent?,
+ ) : OngoingCallModel
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt
index cd442cf..99ed2d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt
@@ -21,7 +21,6 @@
import android.telephony.TelephonyManager.EXTRA_PLMN
import android.telephony.TelephonyManager.EXTRA_SHOW_PLMN
import android.telephony.TelephonyManager.EXTRA_SHOW_SPN
-import android.telephony.TelephonyManager.EXTRA_SPN
import com.android.systemui.log.table.Diffable
import com.android.systemui.log.table.TableRowLogger
@@ -97,8 +96,7 @@
fun Intent.toNetworkNameModel(separator: String): NetworkNameModel? {
val showSpn = getBooleanExtra(EXTRA_SHOW_SPN, false)
- val spn = getStringExtra(EXTRA_SPN)
- val dataSpn = getStringExtra(EXTRA_DATA_SPN)
+ val spn = getStringExtra(EXTRA_DATA_SPN)
val showPlmn = getBooleanExtra(EXTRA_SHOW_PLMN, false)
val plmn = getStringExtra(EXTRA_PLMN)
@@ -114,12 +112,6 @@
}
str.append(spn)
}
- if (showSpn && dataSpn != null) {
- if (str.isNotEmpty()) {
- str.append(separator)
- }
- str.append(dataSpn)
- }
return if (str.isNotEmpty()) NetworkNameModel.IntentDerived(str.toString()) else null
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt
index 16bd7f8..d46aaf4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt
@@ -18,9 +18,12 @@
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
+import android.annotation.IdRes
import android.content.res.ColorStateList
import android.graphics.drawable.GradientDrawable
import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import androidx.lifecycle.Lifecycle
@@ -31,6 +34,7 @@
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.res.R
import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.chips.ui.binder.ChipChronometerBinder
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
@@ -90,7 +94,7 @@
if (Flags.statusBarScreenSharingChips()) {
val chipView: View = view.requireViewById(R.id.ongoing_activity_chip)
val chipContext = chipView.context
- val chipIconView: ImageView =
+ val chipDefaultIconView: ImageView =
chipView.requireViewById(R.id.ongoing_activity_chip_icon)
val chipTimeView: ChipChronometer =
chipView.requireViewById(R.id.ongoing_activity_chip_time)
@@ -105,16 +109,25 @@
when (chipModel) {
is OngoingActivityChipModel.Shown -> {
// Data
- IconViewBinder.bindNullable(chipModel.icon, chipIconView)
+ setChipIcon(chipModel, chipBackgroundView, chipDefaultIconView)
setChipMainContent(chipModel, chipTextView, chipTimeView)
chipView.setOnClickListener(chipModel.onClickListener)
+ updateChipPadding(
+ chipModel,
+ chipBackgroundView,
+ chipTextView,
+ chipTimeView,
+ )
// Accessibility
setChipAccessibility(chipModel, chipView, chipBackgroundView)
// Colors
val textColor = chipModel.colors.text(chipContext)
- chipIconView.imageTintList = ColorStateList.valueOf(textColor)
+ chipDefaultIconView.imageTintList =
+ ColorStateList.valueOf(textColor)
+ chipBackgroundView.getCustomIconView()?.imageTintList =
+ ColorStateList.valueOf(textColor)
chipTimeView.setTextColor(textColor)
chipTextView.setTextColor(textColor)
(chipBackgroundView.background as GradientDrawable).color =
@@ -151,6 +164,69 @@
}
}
+ private fun setChipIcon(
+ chipModel: OngoingActivityChipModel.Shown,
+ backgroundView: ChipBackgroundContainer,
+ defaultIconView: ImageView,
+ ) {
+ // Always remove any previously set custom icon. If we have a new custom icon, we'll re-add
+ // it.
+ backgroundView.removeView(backgroundView.getCustomIconView())
+
+ when (val icon = chipModel.icon) {
+ null -> {
+ defaultIconView.visibility = View.GONE
+ }
+ is OngoingActivityChipModel.ChipIcon.Basic -> {
+ IconViewBinder.bind(icon.impl, defaultIconView)
+ defaultIconView.visibility = View.VISIBLE
+ }
+ is OngoingActivityChipModel.ChipIcon.StatusBarView -> {
+ // Hide the default icon since we'll show this custom icon instead.
+ defaultIconView.visibility = View.GONE
+
+ // Add the new custom icon:
+ // 1. Set up the right visual params.
+ val iconView = icon.impl
+ with(iconView) {
+ id = CUSTOM_ICON_VIEW_ID
+ // TODO(b/354930838): Update the content description to not include "phone" and
+ // maybe include the app name.
+ contentDescription =
+ context.resources.getString(R.string.ongoing_phone_call_content_description)
+ }
+
+ // 2. If we just reinflated the view, we may need to detach the icon view from the
+ // old chip before we reattach it to the new one.
+ // See also: NotificationIconContainerViewBinder#bindIcons.
+ val currentParent = iconView.parent as? ViewGroup
+ if (currentParent != null && currentParent != backgroundView) {
+ currentParent.removeView(iconView)
+ currentParent.removeTransientView(iconView)
+ }
+
+ // 3: Add the icon as the starting view.
+ backgroundView.addView(
+ iconView,
+ /* index= */ 0,
+ generateCustomIconLayoutParams(iconView),
+ )
+ }
+ }
+ }
+
+ private fun View.getCustomIconView(): StatusBarIconView? {
+ return this.findViewById(CUSTOM_ICON_VIEW_ID)
+ }
+
+ private fun generateCustomIconLayoutParams(iconView: ImageView): FrameLayout.LayoutParams {
+ val customIconSize =
+ iconView.context.resources.getDimensionPixelSize(
+ R.dimen.ongoing_activity_chip_embedded_padding_icon_size
+ )
+ return FrameLayout.LayoutParams(customIconSize, customIconSize)
+ }
+
private fun setChipMainContent(
chipModel: OngoingActivityChipModel.Shown,
chipTextView: TextView,
@@ -180,37 +256,93 @@
chipTimeView.visibility = View.GONE
}
}
- updateChipTextPadding(chipModel, chipTextView, chipTimeView)
}
- private fun updateChipTextPadding(
+ private fun updateChipPadding(
chipModel: OngoingActivityChipModel.Shown,
+ backgroundView: View,
chipTextView: TextView,
chipTimeView: ChipChronometer,
) {
- val requiresPadding = chipModel.icon != null
- if (requiresPadding) {
- chipTextView.addChipTextPaddingStart()
- chipTimeView.addChipTextPaddingStart()
+ if (chipModel.icon != null) {
+ if (chipModel.icon is OngoingActivityChipModel.ChipIcon.StatusBarView) {
+ // If the icon is a custom [StatusBarIconView], then it should've come from
+ // `Notification.smallIcon`, which is required to embed its own paddings. We need to
+ // adjust the other paddings to make everything look good :)
+ backgroundView.setBackgroundPaddingForEmbeddedPaddingIcon()
+ chipTextView.setTextPaddingForEmbeddedPaddingIcon()
+ chipTimeView.setTextPaddingForEmbeddedPaddingIcon()
+ } else {
+ backgroundView.setBackgroundPaddingForNormalIcon()
+ chipTextView.setTextPaddingForNormalIcon()
+ chipTimeView.setTextPaddingForNormalIcon()
+ }
} else {
- chipTextView.removeChipTextPaddingStart()
- chipTimeView.removeChipTextPaddingStart()
+ backgroundView.setBackgroundPaddingForNoIcon()
+ chipTextView.setTextPaddingForNoIcon()
+ chipTimeView.setTextPaddingForNoIcon()
}
}
- private fun View.addChipTextPaddingStart() {
+ private fun View.setTextPaddingForEmbeddedPaddingIcon() {
+ val newPaddingEnd =
+ context.resources.getDimensionPixelSize(
+ R.dimen.ongoing_activity_chip_text_end_padding_for_embedded_padding_icon
+ )
+ setPaddingRelative(
+ // The icon should embed enough padding between the icon and time view.
+ /* start= */ 0,
+ this.paddingTop,
+ newPaddingEnd,
+ this.paddingBottom,
+ )
+ }
+
+ private fun View.setTextPaddingForNormalIcon() {
this.setPaddingRelative(
this.context.resources.getDimensionPixelSize(
R.dimen.ongoing_activity_chip_icon_text_padding
),
paddingTop,
- paddingEnd,
+ // The background view will contain the right end padding.
+ /* end= */ 0,
paddingBottom,
)
}
- private fun View.removeChipTextPaddingStart() {
- this.setPaddingRelative(/* start= */ 0, paddingTop, paddingEnd, paddingBottom)
+ private fun View.setTextPaddingForNoIcon() {
+ // The background view will have even start & end paddings, so we don't want the text view
+ // to add any additional padding.
+ this.setPaddingRelative(/* start= */ 0, paddingTop, /* end= */ 0, paddingBottom)
+ }
+
+ private fun View.setBackgroundPaddingForEmbeddedPaddingIcon() {
+ val sidePadding =
+ context.resources.getDimensionPixelSize(
+ R.dimen.ongoing_activity_chip_side_padding_for_embedded_padding_icon
+ )
+ setPaddingRelative(
+ sidePadding,
+ paddingTop,
+ sidePadding,
+ paddingBottom,
+ )
+ }
+
+ private fun View.setBackgroundPaddingForNormalIcon() {
+ val sidePadding =
+ context.resources.getDimensionPixelSize(R.dimen.ongoing_activity_chip_side_padding)
+ setPaddingRelative(
+ sidePadding,
+ paddingTop,
+ sidePadding,
+ paddingBottom,
+ )
+ }
+
+ private fun View.setBackgroundPaddingForNoIcon() {
+ // The padding for the normal icon is also appropriate for no icon.
+ setBackgroundPaddingForNormalIcon()
}
private fun setChipAccessibility(
@@ -269,6 +401,10 @@
)
.start()
}
+
+ companion object {
+ @IdRes private val CUSTOM_ICON_VIEW_ID = R.id.ongoing_activity_chip_custom_icon
+ }
}
/** Listener for various events that may affect the status bar's visibility. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt
index 7a521a6..efd60f6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt
@@ -18,11 +18,15 @@
import android.content.Context
import android.provider.Settings
+import android.provider.Settings.Secure.ZEN_DURATION_FOREVER
+import android.provider.Settings.Secure.ZEN_DURATION_PROMPT
+import android.util.Log
import androidx.concurrent.futures.await
import com.android.settingslib.notification.data.repository.ZenModeRepository
import com.android.settingslib.notification.modes.ZenIconLoader
import com.android.settingslib.notification.modes.ZenMode
import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.shared.notifications.data.repository.NotificationSettingsRepository
import java.time.Duration
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
@@ -34,11 +38,16 @@
* An interactor that performs business logic related to the status and configuration of Zen Mode
* (or Do Not Disturb/DND Mode).
*/
-class ZenModeInteractor @Inject constructor(private val repository: ZenModeRepository) {
+class ZenModeInteractor
+@Inject
+constructor(
+ private val zenModeRepository: ZenModeRepository,
+ private val notificationSettingsRepository: NotificationSettingsRepository,
+) {
private val iconLoader: ZenIconLoader = ZenIconLoader.getInstance()
val isZenModeEnabled: Flow<Boolean> =
- repository.globalZenMode
+ zenModeRepository.globalZenMode
.map {
when (it ?: Settings.Global.ZEN_MODE_OFF) {
Settings.Global.ZEN_MODE_ALARMS -> true
@@ -51,7 +60,9 @@
.distinctUntilChanged()
val areNotificationsHiddenInShade: Flow<Boolean> =
- combine(isZenModeEnabled, repository.consolidatedNotificationPolicy) { dndEnabled, policy ->
+ combine(isZenModeEnabled, zenModeRepository.consolidatedNotificationPolicy) {
+ dndEnabled,
+ policy ->
if (!dndEnabled) {
false
} else {
@@ -61,17 +72,45 @@
}
.distinctUntilChanged()
- val modes: Flow<List<ZenMode>> = repository.modes
+ val modes: Flow<List<ZenMode>> = zenModeRepository.modes
suspend fun getModeIcon(mode: ZenMode, context: Context): Icon {
return Icon.Loaded(mode.getIcon(context, iconLoader).await(), contentDescription = null)
}
- fun activateMode(zenMode: ZenMode, duration: Duration? = null) {
- repository.activateMode(zenMode, duration)
+ fun activateMode(zenMode: ZenMode) {
+ if (zenMode.isManualDnd) {
+ val duration =
+ when (zenDuration) {
+ ZEN_DURATION_PROMPT -> {
+ Log.e(
+ TAG,
+ "Interactor cannot handle showing the zen duration prompt. " +
+ "Please use EnableZenModeDialog when this setting is active."
+ )
+ null
+ }
+ ZEN_DURATION_FOREVER -> null
+ else -> Duration.ofMinutes(zenDuration.toLong())
+ }
+
+ zenModeRepository.activateMode(zenMode, duration)
+ } else {
+ zenModeRepository.activateMode(zenMode)
+ }
}
fun deactivateMode(zenMode: ZenMode) {
- repository.deactivateMode(zenMode)
+ zenModeRepository.deactivateMode(zenMode)
+ }
+
+ private val zenDuration
+ get() = notificationSettingsRepository.zenDuration.value
+
+ fun shouldAskForZenDuration(mode: ZenMode): Boolean =
+ mode.isManualDnd && (zenDuration == ZEN_DURATION_PROMPT)
+
+ companion object {
+ private const val TAG = "ZenModeInteractor"
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt
index 5ffcb34..9422878f6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt
@@ -16,14 +16,18 @@
package com.android.systemui.statusbar.policy.ui.dialog.viewmodel
+import android.app.Dialog
import android.content.Context
import android.content.Intent
import android.provider.Settings.ACTION_AUTOMATIC_ZEN_RULE_SETTINGS
import android.provider.Settings.EXTRA_AUTOMATIC_ZEN_RULE_ID
+import com.android.settingslib.notification.modes.EnableZenModeDialog
import com.android.settingslib.notification.modes.ZenMode
+import com.android.settingslib.notification.modes.ZenModeDialogMetricsLogger
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.res.R
+import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor
import com.android.systemui.statusbar.policy.ui.dialog.ModesDialogDelegate
import javax.inject.Inject
@@ -46,6 +50,8 @@
@Background val bgDispatcher: CoroutineDispatcher,
private val dialogDelegate: ModesDialogDelegate,
) {
+ private val zenDialogMetricsLogger = ZenModeDialogMetricsLogger(context)
+
// Modes that should be displayed in the dialog
private val visibleModes: Flow<List<ZenMode>> =
zenModeInteractor.modes
@@ -91,8 +97,13 @@
zenModeInteractor.deactivateMode(mode)
} else {
if (mode.rule.isManualInvocationAllowed) {
- // TODO(b/346519570): Handle duration for DND mode.
- zenModeInteractor.activateMode(mode)
+ if (zenModeInteractor.shouldAskForZenDuration(mode)) {
+ // NOTE: The dialog handles turning on the mode itself.
+ val dialog = makeZenModeDialog()
+ dialog.show()
+ } else {
+ zenModeInteractor.activateMode(mode)
+ }
}
}
},
@@ -122,4 +133,20 @@
val off = context.resources.getString(R.string.zen_mode_off)
return mode.rule.triggerDescription ?: if (mode.isActive) on else off
}
+
+ private fun makeZenModeDialog(): Dialog {
+ val dialog =
+ EnableZenModeDialog(
+ context,
+ R.style.Theme_SystemUI_Dialog,
+ /* cancelIsNeutral= */ true,
+ zenDialogMetricsLogger
+ )
+ .createDialog()
+ SystemUIDialog.applyFlags(dialog)
+ SystemUIDialog.setShowForAllUsers(dialog, true)
+ SystemUIDialog.registerDismissListener(dialog)
+ SystemUIDialog.setDialogSize(dialog)
+ return dialog
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/TouchpadModule.kt b/packages/SystemUI/src/com/android/systemui/touchpad/TouchpadModule.kt
index c86ac2f..2f74d29 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/TouchpadModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/TouchpadModule.kt
@@ -16,6 +16,7 @@
package com.android.systemui.touchpad
+import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.touchpad.data.repository.TouchpadRepository
import com.android.systemui.touchpad.data.repository.TouchpadRepositoryImpl
import dagger.Binds
@@ -25,5 +26,6 @@
abstract class TouchpadModule {
@Binds
+ @SysUISingleton
abstract fun bindTouchpadRepository(repository: TouchpadRepositoryImpl): TouchpadRepository
}
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt
index 51dfef0..1b00ae2 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt
@@ -16,121 +16,51 @@
package com.android.systemui.touchpad.tutorial.ui.composable
-import android.graphics.ColorFilter
-import android.graphics.PorterDuff
-import android.graphics.PorterDuffColorFilter
-import androidx.activity.compose.BackHandler
-import androidx.annotation.StringRes
-import androidx.compose.animation.animateColorAsState
-import androidx.compose.animation.core.LinearEasing
-import androidx.compose.animation.core.tween
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.BoxScope
-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.fillMaxWidth
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.width
import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.drawBehind
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.toArgb
-import androidx.compose.ui.input.pointer.pointerInteropFilter
-import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.unit.dp
-import com.airbnb.lottie.LottieComposition
-import com.airbnb.lottie.LottieProperty
-import com.airbnb.lottie.compose.LottieAnimation
-import com.airbnb.lottie.compose.LottieCompositionSpec
-import com.airbnb.lottie.compose.LottieConstants
-import com.airbnb.lottie.compose.LottieDynamicProperties
-import com.airbnb.lottie.compose.LottieDynamicProperty
-import com.airbnb.lottie.compose.animateLottieCompositionAsState
-import com.airbnb.lottie.compose.rememberLottieComposition
import com.airbnb.lottie.compose.rememberLottieDynamicProperties
-import com.airbnb.lottie.compose.rememberLottieDynamicProperty
import com.android.compose.theme.LocalAndroidColorScheme
import com.android.systemui.res.R
+import com.android.systemui.touchpad.tutorial.ui.gesture.BackGestureMonitor
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState
-import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.FINISHED
-import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.IN_PROGRESS
-import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGesture.BACK
-import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGestureHandler
-
-data class TutorialScreenColors(
- val backgroundColor: Color,
- val successBackgroundColor: Color,
- val titleColor: Color,
- val animationProperties: LottieDynamicProperties
-)
+import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGestureMonitor
@Composable
fun BackGestureTutorialScreen(
onDoneButtonClicked: () -> Unit,
onBack: () -> Unit,
) {
- val screenColors = rememberScreenColors()
- BackHandler(onBack = onBack)
- var gestureState by remember { mutableStateOf(GestureState.NOT_STARTED) }
- val swipeDistanceThresholdPx =
- LocalContext.current.resources.getDimensionPixelSize(
- com.android.internal.R.dimen.system_gestures_distance_threshold
- )
- val gestureHandler =
- remember(swipeDistanceThresholdPx) {
- TouchpadGestureHandler(
- BACK,
- swipeDistanceThresholdPx,
- onGestureStateChanged = { gestureState = it }
- )
- }
- TouchpadGesturesHandlingBox(gestureHandler, gestureState) {
- GestureTutorialContent(gestureState, onDoneButtonClicked, screenColors)
- }
-}
-
-@Composable
-private fun TouchpadGesturesHandlingBox(
- gestureHandler: TouchpadGestureHandler,
- gestureState: GestureState,
- modifier: Modifier = Modifier,
- content: @Composable BoxScope.() -> Unit
-) {
- Box(
- modifier =
- modifier
- .fillMaxSize()
- // we need to use pointerInteropFilter because some info about touchpad gestures is
- // only available in MotionEvent
- .pointerInteropFilter(
- onTouchEvent = { event ->
- // FINISHED is the final state so we don't need to process touches anymore
- if (gestureState != FINISHED) {
- gestureHandler.onMotionEvent(event)
- } else {
- false
- }
- }
+ val screenConfig =
+ TutorialScreenConfig(
+ colors = rememberScreenColors(),
+ strings =
+ TutorialScreenConfig.Strings(
+ titleResId = R.string.touchpad_back_gesture_action_title,
+ bodyResId = R.string.touchpad_back_gesture_guidance,
+ titleSuccessResId = R.string.touchpad_tutorial_gesture_done,
+ bodySuccessResId = R.string.touchpad_back_gesture_finished
+ ),
+ animations =
+ TutorialScreenConfig.Animations(
+ educationResId = R.raw.trackpad_back_edu,
+ successResId = R.raw.trackpad_back_success
)
- ) {
- content()
- }
+ )
+ val gestureMonitorProvider =
+ object : GestureMonitorProvider {
+ override fun createGestureMonitor(
+ gestureDistanceThresholdPx: Int,
+ gestureStateChangedCallback: (GestureState) -> Unit
+ ): TouchpadGestureMonitor {
+ return BackGestureMonitor(gestureDistanceThresholdPx, gestureStateChangedCallback)
+ }
+ }
+ GestureTutorialScreen(screenConfig, gestureMonitorProvider, onDoneButtonClicked, onBack)
}
@Composable
-private fun rememberScreenColors(): TutorialScreenColors {
+private fun rememberScreenColors(): TutorialScreenConfig.Colors {
val onTertiary = LocalAndroidColorScheme.current.onTertiary
val onTertiaryFixed = LocalAndroidColorScheme.current.onTertiaryFixed
val onTertiaryFixedVariant = LocalAndroidColorScheme.current.onTertiaryFixedVariant
@@ -145,124 +75,12 @@
)
val screenColors =
remember(onTertiaryFixed, surfaceContainer, tertiaryFixedDim, dynamicProperties) {
- TutorialScreenColors(
- backgroundColor = onTertiaryFixed,
- successBackgroundColor = surfaceContainer,
- titleColor = tertiaryFixedDim,
- animationProperties = dynamicProperties,
+ TutorialScreenConfig.Colors(
+ background = onTertiaryFixed,
+ successBackground = surfaceContainer,
+ title = tertiaryFixedDim,
+ animationColors = dynamicProperties,
)
}
return screenColors
}
-
-@Composable
-private fun GestureTutorialContent(
- gestureState: GestureState,
- onDoneButtonClicked: () -> Unit,
- screenColors: TutorialScreenColors
-) {
- val animatedColor by
- animateColorAsState(
- targetValue =
- if (gestureState == FINISHED) screenColors.successBackgroundColor
- else screenColors.backgroundColor,
- animationSpec = tween(durationMillis = 150, easing = LinearEasing),
- label = "backgroundColor"
- )
- Column(
- verticalArrangement = Arrangement.Center,
- modifier =
- Modifier.fillMaxSize()
- .drawBehind { drawRect(animatedColor) }
- .padding(start = 48.dp, top = 124.dp, end = 48.dp, bottom = 48.dp)
- ) {
- Row(modifier = Modifier.fillMaxWidth().weight(1f)) {
- TutorialDescription(
- titleTextId =
- if (gestureState == FINISHED) R.string.touchpad_tutorial_gesture_done
- else R.string.touchpad_back_gesture_action_title,
- titleColor = screenColors.titleColor,
- bodyTextId =
- if (gestureState == FINISHED) R.string.touchpad_back_gesture_finished
- else R.string.touchpad_back_gesture_guidance,
- modifier = Modifier.weight(1f)
- )
- Spacer(modifier = Modifier.width(76.dp))
- TutorialAnimation(
- gestureState,
- screenColors.animationProperties,
- modifier = Modifier.weight(1f).padding(top = 8.dp)
- )
- }
- DoneButton(onDoneButtonClicked = onDoneButtonClicked)
- }
-}
-
-@Composable
-fun TutorialDescription(
- @StringRes titleTextId: Int,
- titleColor: Color,
- @StringRes bodyTextId: Int,
- modifier: Modifier = Modifier
-) {
- Column(verticalArrangement = Arrangement.Top, modifier = modifier) {
- Text(
- text = stringResource(id = titleTextId),
- style = MaterialTheme.typography.displayLarge,
- color = titleColor
- )
- Spacer(modifier = Modifier.height(16.dp))
- Text(
- text = stringResource(id = bodyTextId),
- style = MaterialTheme.typography.bodyLarge,
- color = Color.White
- )
- }
-}
-
-@Composable
-fun TutorialAnimation(
- gestureState: GestureState,
- animationProperties: LottieDynamicProperties,
- modifier: Modifier = Modifier
-) {
- Column(modifier = modifier.fillMaxWidth()) {
- val resId =
- if (gestureState == FINISHED) R.raw.trackpad_back_success else R.raw.trackpad_back_edu
- val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(resId))
- val progress = progressForGestureState(composition, gestureState)
- LottieAnimation(
- composition = composition,
- progress = progress,
- dynamicProperties = animationProperties
- )
- }
-}
-
-@Composable
-private fun progressForGestureState(
- composition: LottieComposition?,
- gestureState: GestureState
-): () -> Float {
- if (gestureState == IN_PROGRESS) {
- return { 0f } // when gesture is in progress, animation should freeze on 1st frame
- } else {
- val iterations = if (gestureState == FINISHED) 1 else LottieConstants.IterateForever
- val animationState by animateLottieCompositionAsState(composition, iterations = iterations)
- return { animationState }
- }
-}
-
-@Composable
-fun rememberColorFilterProperty(
- layerName: String,
- color: Color
-): LottieDynamicProperty<ColorFilter> {
- return rememberLottieDynamicProperty(
- LottieProperty.COLOR_FILTER,
- value = PorterDuffColorFilter(color.toArgb(), PorterDuff.Mode.SRC_ATOP),
- // "**" below means match zero or more layers, so ** layerName ** means find layer with that
- // name at any depth
- keyPath = arrayOf("**", layerName, "**")
- )
-}
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt
new file mode 100644
index 0000000..416c562
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.touchpad.tutorial.ui.composable
+
+import android.graphics.ColorFilter
+import android.graphics.PorterDuff
+import android.graphics.PorterDuffColorFilter
+import androidx.activity.compose.BackHandler
+import androidx.annotation.RawRes
+import androidx.annotation.StringRes
+import androidx.compose.animation.AnimatedContent
+import androidx.compose.animation.EnterTransition
+import androidx.compose.animation.ExitTransition
+import androidx.compose.animation.animateColorAsState
+import androidx.compose.animation.core.LinearEasing
+import androidx.compose.animation.core.snap
+import androidx.compose.animation.core.tween
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
+import androidx.compose.animation.togetherWith
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
+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.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.drawBehind
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.toArgb
+import androidx.compose.ui.input.pointer.pointerInteropFilter
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
+import com.airbnb.lottie.LottieProperty
+import com.airbnb.lottie.compose.LottieAnimation
+import com.airbnb.lottie.compose.LottieCompositionSpec
+import com.airbnb.lottie.compose.LottieConstants
+import com.airbnb.lottie.compose.LottieDynamicProperties
+import com.airbnb.lottie.compose.LottieDynamicProperty
+import com.airbnb.lottie.compose.animateLottieCompositionAsState
+import com.airbnb.lottie.compose.rememberLottieComposition
+import com.airbnb.lottie.compose.rememberLottieDynamicProperty
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.FINISHED
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.IN_PROGRESS
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NOT_STARTED
+import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGestureHandler
+import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGestureMonitor
+
+interface GestureMonitorProvider {
+ fun createGestureMonitor(
+ gestureDistanceThresholdPx: Int,
+ gestureStateChangedCallback: (GestureState) -> Unit
+ ): TouchpadGestureMonitor
+}
+
+@Composable
+fun GestureTutorialScreen(
+ screenConfig: TutorialScreenConfig,
+ gestureMonitorProvider: GestureMonitorProvider,
+ onDoneButtonClicked: () -> Unit,
+ onBack: () -> Unit,
+) {
+ BackHandler(onBack = onBack)
+ var gestureState by remember { mutableStateOf(NOT_STARTED) }
+ val swipeDistanceThresholdPx =
+ LocalContext.current.resources.getDimensionPixelSize(
+ com.android.internal.R.dimen.system_gestures_distance_threshold
+ )
+ val gestureHandler =
+ remember(swipeDistanceThresholdPx) {
+ TouchpadGestureHandler(
+ gestureMonitorProvider.createGestureMonitor(
+ swipeDistanceThresholdPx,
+ gestureStateChangedCallback = { gestureState = it }
+ )
+ )
+ }
+ TouchpadGesturesHandlingBox(gestureHandler, gestureState) {
+ GestureTutorialContent(gestureState, onDoneButtonClicked, screenConfig)
+ }
+}
+
+@Composable
+private fun TouchpadGesturesHandlingBox(
+ gestureHandler: TouchpadGestureHandler,
+ gestureState: GestureState,
+ modifier: Modifier = Modifier,
+ content: @Composable BoxScope.() -> Unit
+) {
+ Box(
+ modifier =
+ modifier
+ .fillMaxSize()
+ // we need to use pointerInteropFilter because some info about touchpad gestures is
+ // only available in MotionEvent
+ .pointerInteropFilter(
+ onTouchEvent = { event ->
+ // FINISHED is the final state so we don't need to process touches anymore
+ if (gestureState == FINISHED) {
+ false
+ } else {
+ gestureHandler.onMotionEvent(event)
+ }
+ }
+ )
+ ) {
+ content()
+ }
+}
+
+@Composable
+private fun GestureTutorialContent(
+ gestureState: GestureState,
+ onDoneButtonClicked: () -> Unit,
+ config: TutorialScreenConfig
+) {
+ val animatedColor by
+ animateColorAsState(
+ targetValue =
+ if (gestureState == FINISHED) config.colors.successBackground
+ else config.colors.background,
+ animationSpec = tween(durationMillis = 150, easing = LinearEasing),
+ label = "backgroundColor"
+ )
+ Column(
+ verticalArrangement = Arrangement.Center,
+ modifier =
+ Modifier.fillMaxSize()
+ .drawBehind { drawRect(animatedColor) }
+ .padding(start = 48.dp, top = 124.dp, end = 48.dp, bottom = 48.dp)
+ ) {
+ Row(modifier = Modifier.fillMaxWidth().weight(1f)) {
+ TutorialDescription(
+ titleTextId =
+ if (gestureState == FINISHED) config.strings.titleSuccessResId
+ else config.strings.titleResId,
+ titleColor = config.colors.title,
+ bodyTextId =
+ if (gestureState == FINISHED) config.strings.bodySuccessResId
+ else config.strings.bodyResId,
+ modifier = Modifier.weight(1f)
+ )
+ Spacer(modifier = Modifier.width(76.dp))
+ TutorialAnimation(
+ gestureState,
+ config,
+ modifier = Modifier.weight(1f).padding(top = 8.dp)
+ )
+ }
+ DoneButton(onDoneButtonClicked = onDoneButtonClicked)
+ }
+}
+
+@Composable
+fun TutorialDescription(
+ @StringRes titleTextId: Int,
+ titleColor: Color,
+ @StringRes bodyTextId: Int,
+ modifier: Modifier = Modifier
+) {
+ Column(verticalArrangement = Arrangement.Top, modifier = modifier) {
+ Text(
+ text = stringResource(id = titleTextId),
+ style = MaterialTheme.typography.displayLarge,
+ color = titleColor
+ )
+ Spacer(modifier = Modifier.height(16.dp))
+ Text(
+ text = stringResource(id = bodyTextId),
+ style = MaterialTheme.typography.bodyLarge,
+ color = Color.White
+ )
+ }
+}
+
+@Composable
+fun TutorialAnimation(
+ gestureState: GestureState,
+ config: TutorialScreenConfig,
+ modifier: Modifier = Modifier
+) {
+ Box(modifier = modifier.fillMaxWidth()) {
+ AnimatedContent(
+ targetState = gestureState,
+ transitionSpec = {
+ if (initialState == NOT_STARTED && targetState == IN_PROGRESS) {
+ val transitionDurationMillis = 150
+ fadeIn(
+ animationSpec = tween(transitionDurationMillis, easing = LinearEasing)
+ ) togetherWith
+ fadeOut(animationSpec = snap(delayMillis = transitionDurationMillis))
+ } else {
+ // empty transition works because all remaining transitions are from IN_PROGRESS
+ // state which shares initial animation frame with both FINISHED and NOT_STARTED
+ EnterTransition.None togetherWith ExitTransition.None
+ }
+ }
+ ) { gestureState ->
+ when (gestureState) {
+ NOT_STARTED ->
+ EducationAnimation(
+ config.animations.educationResId,
+ config.colors.animationColors
+ )
+ IN_PROGRESS ->
+ FrozenSuccessAnimation(
+ config.animations.successResId,
+ config.colors.animationColors
+ )
+ FINISHED ->
+ SuccessAnimation(config.animations.successResId, config.colors.animationColors)
+ }
+ }
+ }
+}
+
+@Composable
+private fun FrozenSuccessAnimation(
+ @RawRes successAnimationId: Int,
+ animationProperties: LottieDynamicProperties
+) {
+ val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(successAnimationId))
+ LottieAnimation(
+ composition = composition,
+ progress = { 0f }, // animation should freeze on 1st frame
+ dynamicProperties = animationProperties,
+ )
+}
+
+@Composable
+private fun EducationAnimation(
+ @RawRes educationAnimationId: Int,
+ animationProperties: LottieDynamicProperties
+) {
+ val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(educationAnimationId))
+ val progress by
+ animateLottieCompositionAsState(composition, iterations = LottieConstants.IterateForever)
+ LottieAnimation(
+ composition = composition,
+ progress = { progress },
+ dynamicProperties = animationProperties,
+ )
+}
+
+@Composable
+private fun SuccessAnimation(
+ @RawRes successAnimationId: Int,
+ animationProperties: LottieDynamicProperties
+) {
+ val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(successAnimationId))
+ val progress by animateLottieCompositionAsState(composition, iterations = 1)
+ LottieAnimation(
+ composition = composition,
+ progress = { progress },
+ dynamicProperties = animationProperties,
+ )
+}
+
+@Composable
+fun rememberColorFilterProperty(
+ layerName: String,
+ color: Color
+): LottieDynamicProperty<ColorFilter> {
+ return rememberLottieDynamicProperty(
+ LottieProperty.COLOR_FILTER,
+ value = PorterDuffColorFilter(color.toArgb(), PorterDuff.Mode.SRC_ATOP),
+ // "**" below means match zero or more layers, so ** layerName ** means find layer with that
+ // name at any depth
+ keyPath = arrayOf("**", layerName, "**")
+ )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/TutorialScreenConfig.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/TutorialScreenConfig.kt
new file mode 100644
index 0000000..d76ceb9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/TutorialScreenConfig.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.touchpad.tutorial.ui.composable
+
+import androidx.annotation.RawRes
+import androidx.annotation.StringRes
+import androidx.compose.ui.graphics.Color
+import com.airbnb.lottie.compose.LottieDynamicProperties
+
+data class TutorialScreenConfig(
+ val colors: Colors,
+ val strings: Strings,
+ val animations: Animations
+) {
+
+ data class Colors(
+ val background: Color,
+ val successBackground: Color,
+ val title: Color,
+ val animationColors: LottieDynamicProperties
+ )
+
+ data class Strings(
+ @StringRes val titleResId: Int,
+ @StringRes val bodyResId: Int,
+ @StringRes val titleSuccessResId: Int,
+ @StringRes val bodySuccessResId: Int,
+ )
+
+ data class Animations(
+ @RawRes val educationResId: Int,
+ @RawRes val successResId: Int,
+ )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitor.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitor.kt
index 6fa9bcd..e3666ce 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitor.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitor.kt
@@ -16,55 +16,26 @@
package com.android.systemui.touchpad.tutorial.ui.gesture
-import android.view.MotionEvent
-import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.FINISHED
-import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.IN_PROGRESS
-import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NOT_STARTED
import kotlin.math.abs
-/**
- * Monitor for touchpad gestures that calls [gestureStateChangedCallback] when [GestureState]
- * changes. All tracked motion events should be passed to [processTouchpadEvent]
- */
-interface TouchpadGestureMonitor {
-
- val gestureDistanceThresholdPx: Int
- val gestureStateChangedCallback: (GestureState) -> Unit
-
- fun processTouchpadEvent(event: MotionEvent)
-}
-
+/** Monitors for touchpad back gesture, that is three fingers swiping left or right */
class BackGestureMonitor(
override val gestureDistanceThresholdPx: Int,
override val gestureStateChangedCallback: (GestureState) -> Unit
-) : TouchpadGestureMonitor {
-
- private var xStart = 0f
-
- override fun processTouchpadEvent(event: MotionEvent) {
- val action = event.actionMasked
- when (action) {
- MotionEvent.ACTION_DOWN -> {
- if (isThreeFingerTouchpadSwipe(event)) {
- xStart = event.x
- gestureStateChangedCallback(IN_PROGRESS)
+) :
+ TouchpadGestureMonitor by ThreeFingerGestureMonitor(
+ gestureDistanceThresholdPx = gestureDistanceThresholdPx,
+ gestureStateChangedCallback = gestureStateChangedCallback,
+ donePredicate =
+ object : GestureDonePredicate {
+ override fun wasGestureDone(
+ startX: Float,
+ startY: Float,
+ endX: Float,
+ endY: Float
+ ): Boolean {
+ val distance = abs(endX - startX)
+ return distance >= gestureDistanceThresholdPx
}
}
- MotionEvent.ACTION_UP -> {
- if (isThreeFingerTouchpadSwipe(event)) {
- val distance = abs(event.x - xStart)
- if (distance >= gestureDistanceThresholdPx) {
- gestureStateChangedCallback(FINISHED)
- } else {
- gestureStateChangedCallback(NOT_STARTED)
- }
- }
- }
- }
- }
-
- private fun isThreeFingerTouchpadSwipe(event: MotionEvent): Boolean {
- return event.classification == MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE &&
- event.getAxisValue(MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT) == 3f
- }
-}
+ )
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/HomeGestureMonitor.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/HomeGestureMonitor.kt
new file mode 100644
index 0000000..a410f99
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/HomeGestureMonitor.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.touchpad.tutorial.ui.gesture
+
+/** Monitors for touchpad home gesture, that is three fingers swiping up */
+class HomeGestureMonitor(
+ override val gestureDistanceThresholdPx: Int,
+ override val gestureStateChangedCallback: (GestureState) -> Unit
+) :
+ TouchpadGestureMonitor by ThreeFingerGestureMonitor(
+ gestureDistanceThresholdPx = gestureDistanceThresholdPx,
+ gestureStateChangedCallback = gestureStateChangedCallback,
+ donePredicate =
+ object : GestureDonePredicate {
+ override fun wasGestureDone(
+ startX: Float,
+ startY: Float,
+ endX: Float,
+ endY: Float
+ ): Boolean {
+ val distance = startY - endY
+ return distance >= gestureDistanceThresholdPx
+ }
+ }
+ )
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/ThreeFingerGestureMonitor.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/ThreeFingerGestureMonitor.kt
new file mode 100644
index 0000000..377977c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/ThreeFingerGestureMonitor.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.touchpad.tutorial.ui.gesture
+
+import android.view.MotionEvent
+
+interface GestureDonePredicate {
+ /**
+ * Should return if gesture was finished. The only events this predicate receives are ACTION_UP.
+ */
+ fun wasGestureDone(startX: Float, startY: Float, endX: Float, endY: Float): Boolean
+}
+
+/** Common implementation for all three-finger gesture monitors */
+class ThreeFingerGestureMonitor(
+ override val gestureDistanceThresholdPx: Int,
+ override val gestureStateChangedCallback: (GestureState) -> Unit,
+ private val donePredicate: GestureDonePredicate
+) : TouchpadGestureMonitor {
+
+ private var xStart = 0f
+ private var yStart = 0f
+
+ override fun processTouchpadEvent(event: MotionEvent) {
+ val action = event.actionMasked
+ when (action) {
+ MotionEvent.ACTION_DOWN -> {
+ if (isThreeFingerTouchpadSwipe(event)) {
+ xStart = event.x
+ yStart = event.y
+ gestureStateChangedCallback(GestureState.IN_PROGRESS)
+ }
+ }
+ MotionEvent.ACTION_UP -> {
+ if (isThreeFingerTouchpadSwipe(event)) {
+ if (donePredicate.wasGestureDone(xStart, yStart, event.x, event.y)) {
+ gestureStateChangedCallback(GestureState.FINISHED)
+ } else {
+ gestureStateChangedCallback(GestureState.NOT_STARTED)
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGesture.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGesture.kt
deleted file mode 100644
index 190da62..0000000
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGesture.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.touchpad.tutorial.ui.gesture
-
-enum class TouchpadGesture {
- BACK,
- HOME;
-
- fun toMonitor(
- swipeDistanceThresholdPx: Int,
- onStateChanged: (GestureState) -> Unit
- ): TouchpadGestureMonitor {
- return when (this) {
- BACK -> BackGestureMonitor(swipeDistanceThresholdPx, onStateChanged)
- else -> throw IllegalArgumentException("Not implemented yet")
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandler.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandler.kt
index cac2a99..bf85b0a 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandler.kt
@@ -24,14 +24,9 @@
* motion events passed to [onMotionEvent] and will filter touchpad events accordingly
*/
class TouchpadGestureHandler(
- touchpadGesture: TouchpadGesture,
- swipeDistanceThresholdPx: Int,
- onGestureStateChanged: (GestureState) -> Unit
+ private val gestureMonitor: TouchpadGestureMonitor,
) {
- private val gestureRecognition =
- touchpadGesture.toMonitor(swipeDistanceThresholdPx, onStateChanged = onGestureStateChanged)
-
fun onMotionEvent(event: MotionEvent): Boolean {
// events from touchpad have SOURCE_MOUSE and not SOURCE_TOUCHPAD because of legacy reasons
val isFromTouchpad =
@@ -41,7 +36,7 @@
event.actionMasked == MotionEvent.ACTION_DOWN &&
event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)
return if (isFromTouchpad && !buttonClick) {
- gestureRecognition.processTouchpadEvent(event)
+ gestureMonitor.processTouchpadEvent(event)
true
} else {
false
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureMonitor.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureMonitor.kt
new file mode 100644
index 0000000..1d2097d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureMonitor.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.touchpad.tutorial.ui.gesture
+
+import android.view.MotionEvent
+
+/**
+ * Monitor for touchpad gestures that calls [gestureStateChangedCallback] when [GestureState]
+ * changes. All tracked motion events should be passed to [processTouchpadEvent]
+ */
+interface TouchpadGestureMonitor {
+
+ val gestureDistanceThresholdPx: Int
+ val gestureStateChangedCallback: (GestureState) -> Unit
+
+ fun processTouchpadEvent(event: MotionEvent)
+}
+
+fun isThreeFingerTouchpadSwipe(event: MotionEvent) = isNFingerTouchpadSwipe(event, fingerCount = 3)
+
+fun isFourFingerTouchpadSwipe(event: MotionEvent) = isNFingerTouchpadSwipe(event, fingerCount = 4)
+
+private fun isNFingerTouchpadSwipe(event: MotionEvent, fingerCount: Int): Boolean {
+ return event.classification == MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE &&
+ event.getAxisValue(MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT) == fingerCount.toFloat()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximityCheck.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximityCheck.java
index c06a3a1..373417b 100644
--- a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximityCheck.java
+++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximityCheck.java
@@ -86,11 +86,12 @@
}
private void onProximityEvent(ThresholdSensorEvent proximityEvent) {
- mCallbacks.forEach(
+ List<Consumer<Boolean>> oldCallbacks = mCallbacks;
+ mCallbacks = new ArrayList<>();
+ oldCallbacks.forEach(
booleanConsumer ->
booleanConsumer.accept(
proximityEvent == null ? null : proximityEvent.getBelow()));
- mCallbacks.clear();
unregister();
mRegistered.set(false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/SecureSettingsImpl.java b/packages/SystemUI/src/com/android/systemui/util/settings/SecureSettingsImpl.java
index 9c98f43..f1da27f 100644
--- a/packages/SystemUI/src/com/android/systemui/util/settings/SecureSettingsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/util/settings/SecureSettingsImpl.java
@@ -22,23 +22,24 @@
import androidx.annotation.NonNull;
-import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.kotlin.SettingsSingleThreadBackground;
-import javax.inject.Inject;
-
import kotlinx.coroutines.CoroutineDispatcher;
+import javax.inject.Inject;
+
class SecureSettingsImpl implements SecureSettings {
private final ContentResolver mContentResolver;
- private final UserTracker mUserTracker;
+ private final CurrentUserIdProvider mCurrentUserProvider;
private final CoroutineDispatcher mBgDispatcher;
@Inject
- SecureSettingsImpl(ContentResolver contentResolver, UserTracker userTracker,
+ SecureSettingsImpl(
+ ContentResolver contentResolver,
+ CurrentUserIdProvider currentUserProvider,
@SettingsSingleThreadBackground CoroutineDispatcher bgDispatcher) {
mContentResolver = contentResolver;
- mUserTracker = userTracker;
+ mCurrentUserProvider = currentUserProvider;
mBgDispatcher = bgDispatcher;
}
@@ -48,8 +49,8 @@
}
@Override
- public UserTracker getUserTracker() {
- return mUserTracker;
+ public CurrentUserIdProvider getCurrentUserProvider() {
+ return mCurrentUserProvider;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.kt b/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.kt
index 9125a91..0ee997e 100644
--- a/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.kt
@@ -15,6 +15,7 @@
*/
package com.android.systemui.util.settings
+import android.annotation.UserIdInt
import android.content.ContentResolver
import android.database.ContentObserver
import android.net.Uri
@@ -629,4 +630,8 @@
}
}
}
+
+ fun interface CurrentUserIdProvider {
+ @UserIdInt fun getUserId(): Int
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/SystemSettingsImpl.java b/packages/SystemUI/src/com/android/systemui/util/settings/SystemSettingsImpl.java
index 406d95b..1e80357 100644
--- a/packages/SystemUI/src/com/android/systemui/util/settings/SystemSettingsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/util/settings/SystemSettingsImpl.java
@@ -22,23 +22,23 @@
import androidx.annotation.NonNull;
-import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.kotlin.SettingsSingleThreadBackground;
-import javax.inject.Inject;
-
import kotlinx.coroutines.CoroutineDispatcher;
+import javax.inject.Inject;
+
class SystemSettingsImpl implements SystemSettings {
private final ContentResolver mContentResolver;
- private final UserTracker mUserTracker;
+ private final CurrentUserIdProvider mCurrentUserProvider;
private final CoroutineDispatcher mBgCoroutineDispatcher;
@Inject
- SystemSettingsImpl(ContentResolver contentResolver, UserTracker userTracker,
+ SystemSettingsImpl(ContentResolver contentResolver,
+ CurrentUserIdProvider currentUserProvider,
@SettingsSingleThreadBackground CoroutineDispatcher bgDispatcher) {
mContentResolver = contentResolver;
- mUserTracker = userTracker;
+ mCurrentUserProvider = currentUserProvider;
mBgCoroutineDispatcher = bgDispatcher;
}
@@ -48,8 +48,8 @@
}
@Override
- public UserTracker getUserTracker() {
- return mUserTracker;
+ public CurrentUserIdProvider getCurrentUserProvider() {
+ return mCurrentUserProvider;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/UserSettingsProxy.kt b/packages/SystemUI/src/com/android/systemui/util/settings/UserSettingsProxy.kt
index ac7c1ce..9ae8f03 100644
--- a/packages/SystemUI/src/com/android/systemui/util/settings/UserSettingsProxy.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/settings/UserSettingsProxy.kt
@@ -23,7 +23,6 @@
import android.os.UserHandle
import android.provider.Settings.SettingNotFoundException
import com.android.app.tracing.TraceUtils.trace
-import com.android.systemui.settings.UserTracker
import com.android.systemui.util.settings.SettingsProxy.Companion.parseFloat
import com.android.systemui.util.settings.SettingsProxy.Companion.parseFloatOrThrow
import com.android.systemui.util.settings.SettingsProxy.Companion.parseLongOrThrow
@@ -46,8 +45,8 @@
* instances, unifying setting related actions in one place.
*/
interface UserSettingsProxy : SettingsProxy {
- /** Returns that [UserTracker] this instance was constructed with. */
- val userTracker: UserTracker
+ val currentUserProvider: SettingsProxy.CurrentUserIdProvider
+
/** Returns the user id for the associated [ContentResolver]. */
var userId: Int
get() = getContentResolver().userId
@@ -64,7 +63,7 @@
fun getRealUserHandle(userHandle: Int): Int {
return if (userHandle != UserHandle.USER_CURRENT) {
userHandle
- } else userTracker.userId
+ } else currentUserProvider.getUserId()
}
@WorkerThread
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index 14cd202..9ca0591 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -34,7 +34,6 @@
import android.content.res.Configuration;
import android.graphics.Rect;
import android.inputmethodservice.InputMethodService;
-import android.os.IBinder;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
@@ -379,8 +378,8 @@
}
@Override
- public void setImeWindowStatus(int displayId, IBinder token, int vis,
- int backDisposition, boolean showImeSwitcher) {
+ public void setImeWindowStatus(int displayId, int vis, int backDisposition,
+ boolean showImeSwitcher) {
if (displayId == mDisplayTracker.getDefaultDisplayId()
&& (vis & InputMethodService.IME_VISIBLE) != 0) {
oneHanded.stopOneHanded(
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerBaseTest.java
index 07504c7..2b4fc5b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerBaseTest.java
@@ -26,7 +26,6 @@
import com.android.keyguard.logging.KeyguardLogger;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory;
import com.android.systemui.kosmos.KosmosJavaAdapter;
@@ -59,7 +58,6 @@
@Mock protected KeyguardLogger mKeyguardLogger;
@Mock protected KeyguardStatusViewController mControllerMock;
@Mock protected ViewTreeObserver mViewTreeObserver;
- @Mock protected DumpManager mDumpManager;
protected FakeKeyguardRepository mFakeKeyguardRepository;
protected FakePowerRepository mFakePowerRepository;
@@ -90,7 +88,6 @@
mKeyguardLogger,
mKosmos.getInteractionJankMonitor(),
deps.getKeyguardInteractor(),
- mDumpManager,
PowerInteractorFactory.create(
mFakePowerRepository
).getPowerInteractor()) {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
index 0696a4b..8e441a3 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
@@ -140,14 +140,6 @@
}
@Test
- public void correctlyDump() {
- mController.onInit();
- verify(mDumpManager).registerDumpable(eq(mController.getInstanceName()), eq(mController));
- mController.onDestroy();
- verify(mDumpManager, times(1)).unregisterDumpable(eq(mController.getInstanceName()));
- }
-
- @Test
public void onInit_addsOnLayoutChangeListenerToClockSwitch() {
when(mKeyguardStatusView.findViewById(R.id.status_view_media_container)).thenReturn(
mMediaHostContainer);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/extradim/ExtraDimDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/accessibility/extradim/ExtraDimDialogDelegateTest.kt
new file mode 100644
index 0000000..b80836d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/extradim/ExtraDimDialogDelegateTest.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.accessibility.extradim
+
+import android.content.DialogInterface
+import android.testing.TestableLooper
+import android.view.accessibility.AccessibilityManager
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.internal.accessibility.AccessibilityShortcutController
+import com.android.internal.accessibility.common.ShortcutConstants
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testCase
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.model.SysUiState
+import com.android.systemui.res.R
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.advanceUntilIdle
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyLong
+import org.mockito.Mock
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+import org.mockito.kotlin.argumentCaptor
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.verify
+
+/** Tests for [ExtraDimDialogDelegate]. */
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@RunWith(AndroidJUnit4::class)
+class ExtraDimDialogDelegateTest : SysuiTestCase() {
+ @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
+
+ private lateinit var extraDimDialogDelegate: ExtraDimDialogDelegate
+
+ private val kosmos = Kosmos().also { it.testCase = this }
+ private val testScope = kosmos.testScope
+
+ @Mock private lateinit var dialog: SystemUIDialog
+ @Mock private lateinit var accessibilityManager: AccessibilityManager
+ @Mock private lateinit var dialogFactory: SystemUIDialog.Factory
+ @Mock private lateinit var userTracker: UserTracker
+ @Mock private lateinit var sysuiState: SysUiState
+
+ @Before
+ fun setUp() {
+ whenever(sysuiState.setFlag(anyLong(), anyBoolean())).thenReturn(sysuiState)
+ whenever(dialog.context).thenReturn(context)
+
+ extraDimDialogDelegate =
+ ExtraDimDialogDelegate(
+ context,
+ testScope.backgroundScope,
+ kosmos.testDispatcher,
+ dialogFactory,
+ accessibilityManager,
+ userTracker
+ )
+ }
+
+ @Test
+ fun clickButton_removeExtraDimShortcuts() =
+ kosmos.testScope.runTest {
+ extraDimDialogDelegate.beforeCreate(dialog, /* savedInstanceState= */ null)
+
+ val clickListener = argumentCaptor<DialogInterface.OnClickListener>()
+
+ // Verify the button has the right text
+ verify(dialog)
+ .setPositiveButton(
+ eq(R.string.accessibility_deprecate_extra_dim_dialog_button),
+ clickListener.capture()
+ )
+
+ clickListener.firstValue.onClick(dialog, 0)
+ advanceUntilIdle()
+ runCurrent()
+ verify(accessibilityManager)
+ .enableShortcutsForTargets(
+ eq(false),
+ eq(ShortcutConstants.UserShortcutType.ALL),
+ eq(
+ setOf(
+ AccessibilityShortcutController.REDUCE_BRIGHT_COLORS_COMPONENT_NAME
+ .flattenToString()
+ )
+ ),
+ anyInt()
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/extradim/ExtraDimDialogManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/accessibility/extradim/ExtraDimDialogManagerTest.kt
new file mode 100644
index 0000000..1386092
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/extradim/ExtraDimDialogManagerTest.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.accessibility.extradim
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.ActivityStarter
+import javax.inject.Provider
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mock
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+import org.mockito.kotlin.verify
+
+/** Tests for [ExtraDimDialogManager]. */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ExtraDimDialogManagerTest : SysuiTestCase() {
+ @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
+
+ private lateinit var extraDimDialogManager: ExtraDimDialogManager
+
+ @Mock private lateinit var activityStarter: ActivityStarter
+ @Mock private lateinit var dialogProvider: Provider<ExtraDimDialogDelegate>
+
+ @Before
+ fun setUp() {
+ extraDimDialogManager = ExtraDimDialogManager(dialogProvider, activityStarter)
+ }
+
+ @Test
+ fun dismissKeyguardIfNeededAndShowDialog_executeRunnableDismissingKeyguard() {
+ extraDimDialogManager.dismissKeyguardIfNeededAndShowDialog()
+ verify(activityStarter)
+ .executeRunnableDismissingKeyguard(
+ any(),
+ /* cancelAction= */ eq(null),
+ /* dismissShade= */ eq(false),
+ /* afterKeyguardGone= */ eq(true),
+ /* deferred= */ eq(false)
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/extradim/ExtraDimDialogReceiverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/accessibility/extradim/ExtraDimDialogReceiverTest.kt
new file mode 100644
index 0000000..ebe7500
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/extradim/ExtraDimDialogReceiverTest.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.accessibility.extradim
+
+import android.content.Intent
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.server.display.feature.flags.Flags
+import com.android.systemui.SysuiTestCase
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+import org.mockito.kotlin.never
+import org.mockito.kotlin.verify
+
+/** Tests for [ExtraDimDialogReceiver]. */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ExtraDimDialogReceiverTest : SysuiTestCase() {
+ @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
+
+ private lateinit var extraDimDialogReceiver: ExtraDimDialogReceiver
+
+ @Mock private lateinit var extraDimDialogManager: ExtraDimDialogManager
+
+ @Before
+ fun setUp() {
+ extraDimDialogReceiver = ExtraDimDialogReceiver(extraDimDialogManager)
+ mContext
+ .getOrCreateTestableResources()
+ .addOverride(com.android.internal.R.bool.config_evenDimmerEnabled, true)
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_EVEN_DIMMER)
+ fun receiveAction_flagEvenDimmerEnabled_showDialog() {
+ extraDimDialogReceiver.onReceive(mContext, Intent(ExtraDimDialogReceiver.ACTION))
+ verify(extraDimDialogManager).dismissKeyguardIfNeededAndShowDialog()
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_EVEN_DIMMER)
+ fun receiveAction_flagEvenDimmerDisabled_neverShowDialog() {
+ extraDimDialogReceiver.onReceive(mContext, Intent(ExtraDimDialogReceiver.ACTION))
+ verify(extraDimDialogManager, never()).dismissKeyguardIfNeededAndShowDialog()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
index 1e3ee28..dc69cda 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
@@ -35,7 +35,6 @@
import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
import android.testing.ViewUtils
-import android.view.KeyEvent
import android.view.View
import android.view.WindowInsets
import android.view.WindowManager
@@ -202,8 +201,7 @@
val root = container.rootView
// Simulate back invocation
- container.dispatchKeyEvent(KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK))
- container.dispatchKeyEvent(KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK))
+ container.onBackInvoked()
waitForIdleSync()
assertThat(container.parent).isNull()
@@ -217,8 +215,7 @@
val root = container.rootView
// Simulate back invocation
- container.dispatchKeyEvent(KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK))
- container.dispatchKeyEvent(KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK))
+ container.onBackInvoked()
waitForIdleSync()
assertThat(container.parent).isNull()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
index 9df653f..512d946 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
@@ -23,7 +23,6 @@
import android.content.pm.ActivityInfo
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager.NameNotFoundException
-import android.content.res.Configuration
import android.graphics.Bitmap
import android.graphics.Point
import android.graphics.Rect
@@ -44,7 +43,6 @@
import android.view.Surface
import androidx.test.filters.SmallTest
import com.android.app.activityTaskManager
-import com.android.systemui.Flags.FLAG_BP_TALKBACK
import com.android.systemui.Flags.FLAG_CONSTRAINT_BP
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthController
@@ -100,9 +98,10 @@
private const val REQUEST_ID = 4L
private const val CHALLENGE = 2L
private const val DELAY = 1000L
-private const val OP_PACKAGE_NAME = "biometric.testapp"
+private const val OP_PACKAGE_NAME_WITH_APP_LOGO = "biometric.testapp"
private const val OP_PACKAGE_NAME_NO_ICON = "biometric.testapp.noicon"
private const val OP_PACKAGE_NAME_CAN_NOT_BE_FOUND = "can.not.be.found"
+private const val OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO = "should.use.activiy.logo"
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@@ -112,19 +111,21 @@
@JvmField @Rule var mockitoRule = MockitoJUnit.rule()
@Mock private lateinit var authController: AuthController
- @Mock private lateinit var applicationInfoWithIcon: ApplicationInfo
- @Mock private lateinit var applicationInfoNoIcon: ApplicationInfo
+ @Mock private lateinit var applicationInfoWithIconAndDescription: ApplicationInfo
+ @Mock private lateinit var applicationInfoNoIconOrDescription: ApplicationInfo
@Mock private lateinit var activityInfo: ActivityInfo
@Mock private lateinit var runningTaskInfo: RunningTaskInfo
- private val defaultLogoIcon = context.getDrawable(R.drawable.ic_android)
- private val defaultLogoIconWithOverrides = context.getDrawable(R.drawable.ic_add)
+ private val defaultLogoIconFromAppInfo = context.getDrawable(R.drawable.ic_android)
+ private val defaultLogoIconFromActivityInfo = context.getDrawable(R.drawable.ic_add)
private val logoResFromApp = R.drawable.ic_cake
private val logoDrawableFromAppRes = context.getDrawable(logoResFromApp)
private val logoBitmapFromApp = Bitmap.createBitmap(400, 400, Bitmap.Config.RGB_565)
- private val defaultLogoDescription = "Test Android App"
+ private val defaultLogoDescriptionFromAppInfo = "Test Android App"
+ private val defaultLogoDescriptionFromActivityInfo = "Test Coke App"
private val logoDescriptionFromApp = "Test Cake App"
private val packageNameForLogoWithOverrides = "should.use.overridden.logo"
+
/** Prompt panel size padding */
private val smallHorizontalGuidelinePadding =
context.resources.getDimensionPixelSize(
@@ -169,19 +170,23 @@
@Before
fun setup() {
-
// Set up default logo info and app customized info
whenever(kosmos.packageManager.getApplicationInfo(eq(OP_PACKAGE_NAME_NO_ICON), anyInt()))
- .thenReturn(applicationInfoNoIcon)
- whenever(kosmos.packageManager.getApplicationInfo(eq(OP_PACKAGE_NAME), anyInt()))
- .thenReturn(applicationInfoWithIcon)
+ .thenReturn(applicationInfoNoIconOrDescription)
whenever(
kosmos.packageManager.getApplicationInfo(
- eq(packageNameForLogoWithOverrides),
+ eq(OP_PACKAGE_NAME_WITH_APP_LOGO),
anyInt()
)
)
- .thenReturn(applicationInfoWithIcon)
+ .thenReturn(applicationInfoWithIconAndDescription)
+ whenever(
+ kosmos.packageManager.getApplicationInfo(
+ eq(OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO),
+ anyInt()
+ )
+ )
+ .thenReturn(applicationInfoWithIconAndDescription)
whenever(
kosmos.packageManager.getApplicationInfo(
eq(OP_PACKAGE_NAME_CAN_NOT_BE_FOUND),
@@ -191,19 +196,27 @@
.thenThrow(NameNotFoundException())
whenever(kosmos.packageManager.getActivityInfo(any(), anyInt())).thenReturn(activityInfo)
- whenever(kosmos.iconProvider.getIcon(activityInfo)).thenReturn(defaultLogoIconWithOverrides)
- whenever(kosmos.packageManager.getApplicationIcon(applicationInfoWithIcon))
- .thenReturn(defaultLogoIcon)
- whenever(kosmos.packageManager.getApplicationLabel(applicationInfoWithIcon))
- .thenReturn(defaultLogoDescription)
+ whenever(kosmos.iconProvider.getIcon(activityInfo))
+ .thenReturn(defaultLogoIconFromActivityInfo)
+ whenever(activityInfo.loadLabel(kosmos.packageManager))
+ .thenReturn(defaultLogoDescriptionFromActivityInfo)
+
+ whenever(kosmos.packageManager.getApplicationIcon(applicationInfoWithIconAndDescription))
+ .thenReturn(defaultLogoIconFromAppInfo)
+ whenever(kosmos.packageManager.getApplicationLabel(applicationInfoWithIconAndDescription))
+ .thenReturn(defaultLogoDescriptionFromAppInfo)
+ whenever(kosmos.packageManager.getApplicationIcon(applicationInfoNoIconOrDescription))
+ .thenReturn(null)
+ whenever(kosmos.packageManager.getApplicationLabel(applicationInfoNoIconOrDescription))
+ .thenReturn("")
whenever(kosmos.packageManager.getUserBadgedIcon(any(), any())).then { it.getArgument(0) }
whenever(kosmos.packageManager.getUserBadgedLabel(any(), any())).then { it.getArgument(0) }
context.setMockPackageManager(kosmos.packageManager)
overrideResource(logoResFromApp, logoDrawableFromAppRes)
overrideResource(
- R.array.biometric_dialog_package_names_for_logo_with_overrides,
- arrayOf(packageNameForLogoWithOverrides)
+ R.array.config_useActivityLogoForBiometricPrompt,
+ arrayOf(OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO)
)
overrideResource(R.dimen.biometric_dialog_fingerprint_icon_width, mockFingerprintIconWidth)
@@ -233,15 +246,6 @@
kosmos.displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_0)
testCase.fingerprint?.isAnySidefpsType.let {
kosmos.displayStateRepository.setIsInRearDisplayMode(testCase.isInRearDisplayMode)
- if (testCase.isDeviceFolded) {
- kosmos.promptViewModel.iconViewModel.onConfigurationChanged(
- getFoldedConfiguration()
- )
- } else {
- kosmos.promptViewModel.iconViewModel.onConfigurationChanged(
- getUnfoldedConfiguration()
- )
- }
}
promptContentView =
@@ -266,12 +270,8 @@
val authenticated by collectLastValue(kosmos.promptViewModel.isAuthenticated)
val modalities by collectLastValue(kosmos.promptViewModel.modalities)
val iconAsset by collectLastValue(kosmos.promptViewModel.iconViewModel.iconAsset)
- val iconOverlayAsset by
- collectLastValue(kosmos.promptViewModel.iconViewModel.iconOverlayAsset)
val shouldAnimateIconView by
collectLastValue(kosmos.promptViewModel.iconViewModel.shouldAnimateIconView)
- val shouldAnimateIconOverlay by
- collectLastValue(kosmos.promptViewModel.iconViewModel.shouldAnimateIconOverlay)
val iconContentDescriptionId by
collectLastValue(kosmos.promptViewModel.iconViewModel.contentDescriptionId)
val message by collectLastValue(kosmos.promptViewModel.message)
@@ -294,9 +294,7 @@
if ((testCase.isCoex && !forceExplicitFlow) || testCase.isFaceOnly) {
// Face-only or implicit co-ex auth
assertThat(iconAsset).isEqualTo(R.raw.face_dialog_idle_static)
- assertThat(iconOverlayAsset).isEqualTo(-1)
assertThat(shouldAnimateIconView).isEqualTo(false)
- assertThat(shouldAnimateIconOverlay).isEqualTo(false)
}
if (forceExplicitFlow) {
@@ -312,29 +310,22 @@
if ((testCase.isCoex && !forceExplicitFlow) || testCase.isFaceOnly) {
// Face-only or implicit co-ex auth
assertThat(iconAsset).isEqualTo(R.raw.face_dialog_authenticating)
- assertThat(iconOverlayAsset).isEqualTo(-1)
assertThat(iconContentDescriptionId)
.isEqualTo(R.string.biometric_dialog_face_icon_description_authenticating)
assertThat(shouldAnimateIconView).isEqualTo(true)
- assertThat(shouldAnimateIconOverlay).isEqualTo(false)
} else if ((testCase.isCoex && forceExplicitFlow) || testCase.isFingerprintOnly) {
// Fingerprint-only or explicit co-ex auth
if (testCase.sensorType == FingerprintSensorProperties.TYPE_POWER_BUTTON) {
- assertThat(iconAsset).isEqualTo(getSfpsBaseIconAsset())
- assertThat(iconOverlayAsset)
- .isEqualTo(R.raw.biometricprompt_fingerprint_to_error_landscape)
+ assertThat(iconAsset).isEqualTo(getSfpsAsset_fingerprintAuthenticating())
assertThat(iconContentDescriptionId)
.isEqualTo(R.string.security_settings_sfps_enroll_find_sensor_message)
assertThat(shouldAnimateIconView).isEqualTo(true)
- assertThat(shouldAnimateIconOverlay).isEqualTo(false)
} else {
assertThat(iconAsset)
.isEqualTo(R.raw.fingerprint_dialogue_fingerprint_to_error_lottie)
- assertThat(iconOverlayAsset).isEqualTo(-1)
assertThat(iconContentDescriptionId)
.isEqualTo(R.string.fingerprint_dialog_touch_sensor)
assertThat(shouldAnimateIconView).isEqualTo(false)
- assertThat(shouldAnimateIconOverlay).isEqualTo(false)
}
}
@@ -348,14 +339,10 @@
@Test
fun start_authenticating_show_and_clear_error() = runGenericTest {
val iconAsset by collectLastValue(kosmos.promptViewModel.iconViewModel.iconAsset)
- val iconOverlayAsset by
- collectLastValue(kosmos.promptViewModel.iconViewModel.iconOverlayAsset)
val iconContentDescriptionId by
collectLastValue(kosmos.promptViewModel.iconViewModel.contentDescriptionId)
val shouldAnimateIconView by
collectLastValue(kosmos.promptViewModel.iconViewModel.shouldAnimateIconView)
- val shouldAnimateIconOverlay by
- collectLastValue(kosmos.promptViewModel.iconViewModel.shouldAnimateIconOverlay)
val message by collectLastValue(kosmos.promptViewModel.message)
var forceExplicitFlow =
@@ -374,7 +361,6 @@
forceExplicitFlow = true
// Usually done by binder
kosmos.promptViewModel.iconViewModel.setPreviousIconWasError(true)
- kosmos.promptViewModel.iconViewModel.setPreviousIconOverlayWasError(true)
}
assertThat(message?.isError).isEqualTo(true)
@@ -384,70 +370,47 @@
if (testCase.isFaceOnly) {
// Face-only auth
assertThat(iconAsset).isEqualTo(R.raw.face_dialog_dark_to_error)
- assertThat(iconOverlayAsset).isEqualTo(-1)
assertThat(iconContentDescriptionId).isEqualTo(R.string.keyguard_face_failed)
assertThat(shouldAnimateIconView).isEqualTo(true)
- assertThat(shouldAnimateIconOverlay).isEqualTo(false)
// Clear error, go to idle
errorJob.join()
assertThat(iconAsset).isEqualTo(R.raw.face_dialog_error_to_idle)
- assertThat(iconOverlayAsset).isEqualTo(-1)
assertThat(iconContentDescriptionId)
.isEqualTo(R.string.biometric_dialog_face_icon_description_idle)
assertThat(shouldAnimateIconView).isEqualTo(true)
- assertThat(shouldAnimateIconOverlay).isEqualTo(false)
} else if ((testCase.isCoex && forceExplicitFlow) || testCase.isFingerprintOnly) {
// Fingerprint-only or explicit co-ex auth
if (testCase.sensorType == FingerprintSensorProperties.TYPE_POWER_BUTTON) {
- assertThat(iconAsset).isEqualTo(getSfpsBaseIconAsset())
- assertThat(iconOverlayAsset)
- .isEqualTo(R.raw.biometricprompt_fingerprint_to_error_landscape)
+ assertThat(iconAsset).isEqualTo(getSfpsAsset_fingerprintToError())
assertThat(iconContentDescriptionId).isEqualTo(R.string.biometric_dialog_try_again)
assertThat(shouldAnimateIconView).isEqualTo(true)
- assertThat(shouldAnimateIconOverlay).isEqualTo(true)
} else {
assertThat(iconAsset)
.isEqualTo(R.raw.fingerprint_dialogue_fingerprint_to_error_lottie)
- assertThat(iconOverlayAsset).isEqualTo(-1)
assertThat(iconContentDescriptionId).isEqualTo(R.string.biometric_dialog_try_again)
assertThat(shouldAnimateIconView).isEqualTo(true)
- assertThat(shouldAnimateIconOverlay).isEqualTo(false)
}
// Clear error, restart authenticating
errorJob.join()
if (testCase.sensorType == FingerprintSensorProperties.TYPE_POWER_BUTTON) {
- assertThat(iconAsset).isEqualTo(getSfpsBaseIconAsset())
- assertThat(iconOverlayAsset)
- .isEqualTo(R.raw.biometricprompt_symbol_error_to_fingerprint_landscape)
+ assertThat(iconAsset).isEqualTo(getSfpsAsset_errorToFingerprint())
assertThat(iconContentDescriptionId)
.isEqualTo(R.string.security_settings_sfps_enroll_find_sensor_message)
- assertThat(shouldAnimateIconOverlay).isEqualTo(true)
+ assertThat(shouldAnimateIconView).isEqualTo(true)
} else {
assertThat(iconAsset)
.isEqualTo(R.raw.fingerprint_dialogue_error_to_fingerprint_lottie)
- assertThat(iconOverlayAsset).isEqualTo(-1)
assertThat(iconContentDescriptionId)
.isEqualTo(R.string.fingerprint_dialog_touch_sensor)
assertThat(shouldAnimateIconView).isEqualTo(true)
- assertThat(shouldAnimateIconOverlay).isEqualTo(false)
}
}
}
- private fun getSfpsBaseIconAsset(): Int {
- return if (testCase.isInRearDisplayMode) {
- R.raw.biometricprompt_rear_landscape_base
- } else if (testCase.isDeviceFolded) {
- R.raw.biometricprompt_folded_base_default
- } else {
- R.raw.biometricprompt_landscape_base
- }
- }
-
@Test
fun shows_error_to_unlock_or_success() {
// Face-only auth does not use error -> unlock or error -> success assets
@@ -477,9 +440,30 @@
dismissAfterDelay = DELAY
)
- // TODO(b/350121748): SFPS test cases to be added after SFPS assets update
- if (testCase.sensorType != FingerprintSensorProperties.TYPE_POWER_BUTTON) {
- // Non-SFPS (UDFPS / rear-FPS) test cases
+ // SFPS test cases
+ if (testCase.sensorType == FingerprintSensorProperties.TYPE_POWER_BUTTON) {
+ // Covers (1) fingerprint-only (2) co-ex, authenticated by fingerprint
+ if (testCase.authenticatedByFingerprint) {
+ assertThat(iconAsset).isEqualTo(R.raw.biometricprompt_sfps_error_to_success)
+ assertThat(iconContentDescriptionId)
+ .isEqualTo(R.string.security_settings_sfps_enroll_find_sensor_message)
+ assertThat(shouldAnimateIconView).isEqualTo(true)
+ } else { // Covers co-ex, authenticated by face
+ assertThat(iconAsset).isEqualTo(R.raw.biometricprompt_sfps_error_to_unlock)
+ assertThat(iconContentDescriptionId)
+ .isEqualTo(R.string.fingerprint_dialog_authenticated_confirmation)
+ assertThat(shouldAnimateIconView).isEqualTo(true)
+
+ // Confirm authentication
+ kosmos.promptViewModel.confirmAuthenticated()
+
+ assertThat(iconAsset)
+ .isEqualTo(R.raw.biometricprompt_sfps_unlock_to_success)
+ assertThat(iconContentDescriptionId)
+ .isEqualTo(R.string.fingerprint_dialog_touch_sensor)
+ assertThat(shouldAnimateIconView).isEqualTo(true)
+ }
+ } else { // Non-SFPS (UDFPS / rear-FPS) test cases
// Covers (1) fingerprint-only (2) co-ex, authenticated by fingerprint
if (testCase.authenticatedByFingerprint) {
assertThat(iconAsset)
@@ -491,7 +475,7 @@
assertThat(iconAsset)
.isEqualTo(R.raw.fingerprint_dialogue_error_to_unlock_lottie)
assertThat(iconContentDescriptionId)
- .isEqualTo(R.string.fingerprint_dialog_authenticated_confirmation)
+ .isEqualTo(R.string.biometric_dialog_confirm)
assertThat(shouldAnimateIconView).isEqualTo(true)
// Confirm authentication
@@ -515,14 +499,10 @@
if (!testCase.confirmationRequested) {
runGenericTest {
val iconAsset by collectLastValue(kosmos.promptViewModel.iconViewModel.iconAsset)
- val iconOverlayAsset by
- collectLastValue(kosmos.promptViewModel.iconViewModel.iconOverlayAsset)
val iconContentDescriptionId by
collectLastValue(kosmos.promptViewModel.iconViewModel.contentDescriptionId)
val shouldAnimateIconView by
collectLastValue(kosmos.promptViewModel.iconViewModel.shouldAnimateIconView)
- val shouldAnimateIconOverlay by
- collectLastValue(kosmos.promptViewModel.iconViewModel.shouldAnimateIconOverlay)
verifyIconSize()
kosmos.promptViewModel.showAuthenticated(
@@ -533,33 +513,24 @@
if (testCase.isFingerprintOnly) {
// Fingerprint icon asset assertions
if (testCase.sensorType == FingerprintSensorProperties.TYPE_POWER_BUTTON) {
- assertThat(iconAsset).isEqualTo(getSfpsBaseIconAsset())
- assertThat(iconOverlayAsset)
- .isEqualTo(
- R.raw.biometricprompt_symbol_fingerprint_to_success_landscape
- )
+ assertThat(iconAsset).isEqualTo(getSfpsAsset_fingerprintToSuccess())
assertThat(iconContentDescriptionId)
.isEqualTo(R.string.security_settings_sfps_enroll_find_sensor_message)
assertThat(shouldAnimateIconView).isEqualTo(true)
- assertThat(shouldAnimateIconOverlay).isEqualTo(true)
} else {
assertThat(iconAsset)
.isEqualTo(R.raw.fingerprint_dialogue_fingerprint_to_success_lottie)
- assertThat(iconOverlayAsset).isEqualTo(-1)
assertThat(iconContentDescriptionId)
.isEqualTo(R.string.fingerprint_dialog_touch_sensor)
assertThat(shouldAnimateIconView).isEqualTo(true)
- assertThat(shouldAnimateIconOverlay).isEqualTo(false)
}
} else if (testCase.isFaceOnly || testCase.isCoex) {
// Face icon asset assertions
// If co-ex, use implicit flow (explicit flow always requires confirmation)
assertThat(iconAsset).isEqualTo(R.raw.face_dialog_dark_to_checkmark)
- assertThat(iconOverlayAsset).isEqualTo(-1)
assertThat(iconContentDescriptionId)
.isEqualTo(R.string.biometric_dialog_face_icon_description_authenticated)
assertThat(shouldAnimateIconView).isEqualTo(true)
- assertThat(shouldAnimateIconOverlay).isEqualTo(false)
}
}
}
@@ -570,14 +541,10 @@
if (testCase.authenticatedByFace && testCase.confirmationRequested) {
runGenericTest {
val iconAsset by collectLastValue(kosmos.promptViewModel.iconViewModel.iconAsset)
- val iconOverlayAsset by
- collectLastValue(kosmos.promptViewModel.iconViewModel.iconOverlayAsset)
val iconContentDescriptionId by
collectLastValue(kosmos.promptViewModel.iconViewModel.contentDescriptionId)
val shouldAnimateIconView by
collectLastValue(kosmos.promptViewModel.iconViewModel.shouldAnimateIconView)
- val shouldAnimateIconOverlay by
- collectLastValue(kosmos.promptViewModel.iconViewModel.shouldAnimateIconOverlay)
val forceExplicitFlow = testCase.isCoex && testCase.confirmationRequested
verifyIconSize(forceExplicitFlow = forceExplicitFlow)
@@ -589,21 +556,21 @@
if (testCase.isFaceOnly) {
assertThat(iconAsset).isEqualTo(R.raw.face_dialog_wink_from_dark)
- assertThat(iconOverlayAsset).isEqualTo(-1)
assertThat(iconContentDescriptionId)
.isEqualTo(R.string.biometric_dialog_face_icon_description_authenticated)
assertThat(shouldAnimateIconView).isEqualTo(true)
- assertThat(shouldAnimateIconOverlay).isEqualTo(false)
} else if (testCase.isCoex) { // explicit flow, confirmation requested
- // TODO: Update when SFPS co-ex is implemented
- if (testCase.sensorType != FingerprintSensorProperties.TYPE_POWER_BUTTON) {
- assertThat(iconAsset)
- .isEqualTo(R.raw.fingerprint_dialogue_fingerprint_to_unlock_lottie)
- assertThat(iconOverlayAsset).isEqualTo(-1)
+ if (testCase.sensorType == FingerprintSensorProperties.TYPE_POWER_BUTTON) {
+ assertThat(iconAsset).isEqualTo(getSfpsAsset_fingerprintToUnlock())
assertThat(iconContentDescriptionId)
.isEqualTo(R.string.fingerprint_dialog_authenticated_confirmation)
assertThat(shouldAnimateIconView).isEqualTo(true)
- assertThat(shouldAnimateIconOverlay).isEqualTo(false)
+ } else {
+ assertThat(iconAsset)
+ .isEqualTo(R.raw.fingerprint_dialogue_fingerprint_to_unlock_lottie)
+ assertThat(iconContentDescriptionId)
+ .isEqualTo(R.string.biometric_dialog_confirm)
+ assertThat(shouldAnimateIconView).isEqualTo(true)
}
}
}
@@ -615,14 +582,10 @@
if (testCase.authenticatedByFace && testCase.confirmationRequested) {
runGenericTest {
val iconAsset by collectLastValue(kosmos.promptViewModel.iconViewModel.iconAsset)
- val iconOverlayAsset by
- collectLastValue(kosmos.promptViewModel.iconViewModel.iconOverlayAsset)
val iconContentDescriptionId by
collectLastValue(kosmos.promptViewModel.iconViewModel.contentDescriptionId)
val shouldAnimateIconView by
collectLastValue(kosmos.promptViewModel.iconViewModel.shouldAnimateIconView)
- val shouldAnimateIconOverlay by
- collectLastValue(kosmos.promptViewModel.iconViewModel.shouldAnimateIconOverlay)
val forceExplicitFlow = testCase.isCoex && testCase.confirmationRequested
verifyIconSize(forceExplicitFlow = forceExplicitFlow)
@@ -635,32 +598,66 @@
if (testCase.isFaceOnly) {
assertThat(iconAsset).isEqualTo(R.raw.face_dialog_dark_to_checkmark)
- assertThat(iconOverlayAsset).isEqualTo(-1)
assertThat(iconContentDescriptionId)
.isEqualTo(R.string.biometric_dialog_face_icon_description_confirmed)
assertThat(shouldAnimateIconView).isEqualTo(true)
- assertThat(shouldAnimateIconOverlay).isEqualTo(false)
}
// explicit flow because confirmation requested
if (testCase.isCoex) {
- // TODO: Update when SFPS co-ex is implemented
- if (testCase.sensorType != FingerprintSensorProperties.TYPE_POWER_BUTTON) {
+ if (testCase.sensorType == FingerprintSensorProperties.TYPE_POWER_BUTTON) {
+ assertThat(iconAsset)
+ .isEqualTo(R.raw.biometricprompt_sfps_unlock_to_success)
+ assertThat(shouldAnimateIconView).isEqualTo(true)
+ } else {
assertThat(iconAsset)
.isEqualTo(
R.raw.fingerprint_dialogue_unlocked_to_checkmark_success_lottie
)
- assertThat(iconOverlayAsset).isEqualTo(-1)
assertThat(iconContentDescriptionId)
.isEqualTo(R.string.fingerprint_dialog_touch_sensor)
assertThat(shouldAnimateIconView).isEqualTo(true)
- assertThat(shouldAnimateIconOverlay).isEqualTo(false)
}
}
}
}
}
+ private fun getSfpsAsset_fingerprintAuthenticating(): Int =
+ if (testCase.isInRearDisplayMode) {
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_authenticating
+ } else {
+ R.raw.biometricprompt_sfps_fingerprint_authenticating
+ }
+
+ private fun getSfpsAsset_fingerprintToError(): Int =
+ if (testCase.isInRearDisplayMode) {
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_error
+ } else {
+ R.raw.biometricprompt_sfps_fingerprint_to_error
+ }
+
+ private fun getSfpsAsset_fingerprintToUnlock(): Int =
+ if (testCase.isInRearDisplayMode) {
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_unlock
+ } else {
+ R.raw.biometricprompt_sfps_fingerprint_to_unlock
+ }
+
+ private fun getSfpsAsset_errorToFingerprint(): Int =
+ if (testCase.isInRearDisplayMode) {
+ R.raw.biometricprompt_sfps_rear_display_error_to_fingerprint
+ } else {
+ R.raw.biometricprompt_sfps_error_to_fingerprint
+ }
+
+ private fun getSfpsAsset_fingerprintToSuccess(): Int =
+ if (testCase.isInRearDisplayMode) {
+ R.raw.biometricprompt_sfps_rear_display_fingerprint_to_success
+ } else {
+ R.raw.biometricprompt_sfps_fingerprint_to_success
+ }
+
@Test
fun shows_authenticated_with_no_errors() = runGenericTest {
// this case can't happen until fingerprint is started
@@ -763,36 +760,19 @@
.isEqualTo(HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING)
}
+ // biometricprompt_sfps_fingerprint_authenticating reused across rotations
+ // Other SFPS assets change across rotations, testing authenticated asset
@Test
- fun sfpsIconUpdates_onFoldConfigurationChanged() {
- if (
- testCase.sensorType == FingerprintSensorProperties.TYPE_POWER_BUTTON &&
- !testCase.isInRearDisplayMode
- ) {
- runGenericTest {
- val currentIcon by collectLastValue(kosmos.promptViewModel.iconViewModel.iconAsset)
-
- kosmos.promptViewModel.iconViewModel.onConfigurationChanged(
- getFoldedConfiguration()
- )
- val foldedIcon = currentIcon
-
- kosmos.promptViewModel.iconViewModel.onConfigurationChanged(
- getUnfoldedConfiguration()
- )
- val unfoldedIcon = currentIcon
-
- assertThat(foldedIcon).isNotEqualTo(unfoldedIcon)
- }
- }
- }
-
- @Test
- fun sfpsIconUpdates_onRotation() {
+ fun sfpsAuthenticatedIconUpdates_onRotation() {
if (testCase.sensorType == FingerprintSensorProperties.TYPE_POWER_BUTTON) {
runGenericTest {
val currentIcon by collectLastValue(kosmos.promptViewModel.iconViewModel.iconAsset)
+ kosmos.promptViewModel.showAuthenticated(
+ modality = testCase.authenticatedModality,
+ dismissAfterDelay = DELAY
+ )
+
kosmos.displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_0)
val iconRotation0 = currentIcon
@@ -805,9 +785,12 @@
kosmos.displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_270)
val iconRotation270 = currentIcon
- assertThat(iconRotation0).isEqualTo(iconRotation180)
assertThat(iconRotation0).isNotEqualTo(iconRotation90)
+ assertThat(iconRotation0).isNotEqualTo(iconRotation180)
assertThat(iconRotation0).isNotEqualTo(iconRotation270)
+ assertThat(iconRotation90).isNotEqualTo(iconRotation180)
+ assertThat(iconRotation90).isNotEqualTo(iconRotation270)
+ assertThat(iconRotation180).isNotEqualTo(iconRotation270)
}
}
}
@@ -1356,7 +1339,6 @@
}
@Test
- @EnableFlags(FLAG_BP_TALKBACK)
fun hint_for_talkback_guidance() = runGenericTest {
val hint by collectLastValue(kosmos.promptViewModel.accessibilityHint)
@@ -1379,7 +1361,6 @@
}
@Test
- @EnableFlags(FLAG_BP_TALKBACK)
fun no_hint_for_talkback_guidance_after_auth() = runGenericTest {
val hint by collectLastValue(kosmos.promptViewModel.accessibilityHint)
@@ -1440,36 +1421,41 @@
@EnableFlags(FLAG_CUSTOM_BIOMETRIC_PROMPT, FLAG_CONSTRAINT_BP)
fun logo_nullIfPkgNameNotFound() =
runGenericTest(packageName = OP_PACKAGE_NAME_CAN_NOT_BE_FOUND) {
- val logo by collectLastValue(kosmos.promptViewModel.logo)
- assertThat(logo).isNull()
+ val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
+ assertThat(logoInfo).isNotNull()
+ assertThat(logoInfo!!.first).isNull()
}
@Test
@EnableFlags(FLAG_CUSTOM_BIOMETRIC_PROMPT, FLAG_CONSTRAINT_BP)
- fun logo_defaultWithOverrides() =
- runGenericTest(packageName = packageNameForLogoWithOverrides) {
- val logo by collectLastValue(kosmos.promptViewModel.logo)
+ fun logo_defaultFromActivityInfo() =
+ runGenericTest(packageName = OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO) {
+ val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
- // 1. PM.getApplicationInfo(packageNameForLogoWithOverrides) is set to return
- // applicationInfoWithIcon with defaultLogoIcon,
- // 2. iconProvider.getIcon() is set to return defaultLogoIconForGMSCore
- // For the apps with packageNameForLogoWithOverrides, 2 should be called instead of 1
- assertThat(logo).isEqualTo(defaultLogoIconWithOverrides)
+ // 1. PM.getApplicationInfo(OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO) is set to return
+ // applicationInfoWithIconAndDescription with "defaultLogoIconFromAppInfo",
+ // 2. iconProvider.getIcon(activityInfo) is set to return
+ // "defaultLogoIconFromActivityInfo"
+ // For the apps with OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO, 2 should be called instead of 1
+ assertThat(logoInfo).isNotNull()
+ assertThat(logoInfo!!.first).isEqualTo(defaultLogoIconFromActivityInfo)
}
@Test
@EnableFlags(FLAG_CUSTOM_BIOMETRIC_PROMPT, FLAG_CONSTRAINT_BP)
fun logo_defaultIsNull() =
runGenericTest(packageName = OP_PACKAGE_NAME_NO_ICON) {
- val logo by collectLastValue(kosmos.promptViewModel.logo)
- assertThat(logo).isNull()
+ val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
+ assertThat(logoInfo).isNotNull()
+ assertThat(logoInfo!!.first).isNull()
}
@Test
@EnableFlags(FLAG_CUSTOM_BIOMETRIC_PROMPT, FLAG_CONSTRAINT_BP)
fun logo_default() = runGenericTest {
- val logo by collectLastValue(kosmos.promptViewModel.logo)
- assertThat(logo).isEqualTo(defaultLogoIcon)
+ val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
+ assertThat(logoInfo).isNotNull()
+ assertThat(logoInfo!!.first).isEqualTo(defaultLogoIconFromAppInfo)
}
@Test
@@ -1477,47 +1463,60 @@
fun logo_resSetByApp() =
runGenericTest(logoRes = logoResFromApp) {
val expectedBitmap = context.getDrawable(logoResFromApp).toBitmap()
- val logo by collectLastValue(kosmos.promptViewModel.logo)
- assertThat((logo as BitmapDrawable).bitmap.sameAs(expectedBitmap)).isTrue()
+ val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
+ assertThat(logoInfo).isNotNull()
+ assertThat((logoInfo!!.first as BitmapDrawable).bitmap.sameAs(expectedBitmap)).isTrue()
}
@Test
@EnableFlags(FLAG_CUSTOM_BIOMETRIC_PROMPT, FLAG_CONSTRAINT_BP)
fun logo_bitmapSetByApp() =
runGenericTest(logoBitmap = logoBitmapFromApp) {
- val logo by collectLastValue(kosmos.promptViewModel.logo)
- assertThat((logo as BitmapDrawable).bitmap).isEqualTo(logoBitmapFromApp)
+ val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
+ assertThat((logoInfo!!.first as BitmapDrawable).bitmap).isEqualTo(logoBitmapFromApp)
}
@Test
@EnableFlags(FLAG_CUSTOM_BIOMETRIC_PROMPT, FLAG_CONSTRAINT_BP)
fun logoDescription_emptyIfPkgNameNotFound() =
runGenericTest(packageName = OP_PACKAGE_NAME_CAN_NOT_BE_FOUND) {
- val logoDescription by collectLastValue(kosmos.promptViewModel.logoDescription)
- assertThat(logoDescription).isEqualTo("")
+ val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
+ assertThat(logoInfo!!.second).isEqualTo("")
+ }
+
+ @Test
+ @EnableFlags(FLAG_CUSTOM_BIOMETRIC_PROMPT, FLAG_CONSTRAINT_BP)
+ fun logoDescription_defaultFromActivityInfo() =
+ runGenericTest(packageName = OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO) {
+ val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
+ // 1. PM.getApplicationInfo(packageNameForLogoWithOverrides) is set to return
+ // applicationInfoWithIconAndDescription with defaultLogoDescription,
+ // 2. activityInfo.loadLabel() is set to return defaultLogoDescriptionWithOverrides
+ // For the apps with packageNameForLogoWithOverrides, 2 should be called instead of 1
+ assertThat(logoInfo!!.second).isEqualTo(defaultLogoDescriptionFromActivityInfo)
}
@Test
@EnableFlags(FLAG_CUSTOM_BIOMETRIC_PROMPT, FLAG_CONSTRAINT_BP)
fun logoDescription_defaultIsEmpty() =
runGenericTest(packageName = OP_PACKAGE_NAME_NO_ICON) {
- val logoDescription by collectLastValue(kosmos.promptViewModel.logoDescription)
- assertThat(logoDescription).isEqualTo("")
+ val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
+ assertThat(logoInfo!!.second).isEqualTo("")
}
@Test
@EnableFlags(FLAG_CUSTOM_BIOMETRIC_PROMPT, FLAG_CONSTRAINT_BP)
fun logoDescription_default() = runGenericTest {
- val logoDescription by collectLastValue(kosmos.promptViewModel.logoDescription)
- assertThat(logoDescription).isEqualTo(defaultLogoDescription)
+ val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
+ assertThat(logoInfo!!.second).isEqualTo(defaultLogoDescriptionFromAppInfo)
}
@Test
@EnableFlags(FLAG_CUSTOM_BIOMETRIC_PROMPT, FLAG_CONSTRAINT_BP)
fun logoDescription_setByApp() =
runGenericTest(logoDescription = logoDescriptionFromApp) {
- val logoDescription by collectLastValue(kosmos.promptViewModel.logoDescription)
- assertThat(logoDescription).isEqualTo(logoDescriptionFromApp)
+ val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
+ assertThat(logoInfo!!.second).isEqualTo(logoDescriptionFromApp)
}
@Test
@@ -1692,7 +1691,7 @@
logoRes: Int = 0,
logoBitmap: Bitmap? = null,
logoDescription: String? = null,
- packageName: String = OP_PACKAGE_NAME,
+ packageName: String = OP_PACKAGE_NAME_WITH_APP_LOGO,
block: suspend TestScope.() -> Unit,
) {
val topActivity = ComponentName(packageName, "test app")
@@ -1789,18 +1788,6 @@
.first(),
authenticatedModality = BiometricModality.Fingerprint,
isInRearDisplayMode = false,
- isDeviceFolded = false
- ),
- TestCase(
- fingerprint =
- fingerprintSensorPropertiesInternal(
- strong = true,
- sensorType = FingerprintSensorProperties.TYPE_POWER_BUTTON
- )
- .first(),
- authenticatedModality = BiometricModality.Fingerprint,
- isInRearDisplayMode = false,
- isDeviceFolded = true
),
TestCase(
fingerprint =
@@ -1811,7 +1798,6 @@
.first(),
authenticatedModality = BiometricModality.Fingerprint,
isInRearDisplayMode = true,
- isDeviceFolded = false
),
TestCase(
fingerprint =
@@ -1886,7 +1872,6 @@
val fingerprint: FingerprintSensorPropertiesInternal? = null,
val face: FaceSensorPropertiesInternal? = null,
val isInRearDisplayMode: Boolean = false,
- val isDeviceFolded: Boolean = false,
val authenticatedModality: BiometricModality,
val confirmationRequested: Boolean = false,
) {
@@ -1902,9 +1887,8 @@
face != null -> "face only"
else -> "?"
}
- return "[$modality, isInRearDisplayMode: $isInRearDisplayMode, " +
- "isDeviceFolded: $isDeviceFolded, by: $authenticatedModality, " +
- "confirm: $confirmationRequested]"
+ return "[$modality, isInRearDisplayMode: $isInRearDisplayMode, by: " +
+ "$authenticatedModality, confirm: $confirmationRequested]"
}
fun expectConfirmation(atLeastOneFailure: Boolean): Boolean =
@@ -1951,7 +1935,7 @@
logoResFromApp: Int = 0,
logoBitmapFromApp: Bitmap? = null,
logoDescriptionFromApp: String? = null,
- packageName: String = OP_PACKAGE_NAME,
+ packageName: String = OP_PACKAGE_NAME_WITH_APP_LOGO,
) {
val info =
PromptInfo().apply {
@@ -1984,21 +1968,3 @@
withArgCaptor<AuthController.Callback> {
Mockito.verify(this@captureCallback).addCallback(capture())
}
-
-/** Get folded device configuration */
-fun getFoldedConfiguration(): Configuration {
- val testConfig = Configuration()
- val folded = INNER_SCREEN_SMALLEST_SCREEN_WIDTH_THRESHOLD_DP - 1
- testConfig.smallestScreenWidthDp = folded
- return testConfig
-}
-
-/** Get unfolded device configuration */
-fun getUnfoldedConfiguration(): Configuration {
- val testConfig = Configuration()
- val unfolded = INNER_SCREEN_SMALLEST_SCREEN_WIDTH_THRESHOLD_DP + 1
- testConfig.smallestScreenWidthDp = unfolded
- return testConfig
-}
-
-internal const val INNER_SCREEN_SMALLEST_SCREEN_WIDTH_THRESHOLD_DP = 600
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
index 0489d81..945f86c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
@@ -89,10 +89,7 @@
verify(taskView).startActivity(any(), any(), capture(optionsCaptor), any())
assertThat(optionsCaptor.value.pendingIntentBackgroundActivityStartMode)
- .isAnyOf(ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED,
- ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS)
- assertThat(optionsCaptor.value.isPendingIntentBackgroundActivityLaunchAllowedByPermission)
- .isTrue()
+ .isEqualTo(ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS)
assertThat(optionsCaptor.value.taskAlwaysOnTop).isTrue()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricsAllowedInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricsAllowedInteractorTest.kt
new file mode 100644
index 0000000..295a626
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricsAllowedInteractorTest.kt
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.deviceentry.domain.interactor
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.data.repository.FaceSensorInfo
+import com.android.systemui.biometrics.data.repository.fakeFacePropertyRepository
+import com.android.systemui.biometrics.data.repository.fakeFingerprintPropertyRepository
+import com.android.systemui.biometrics.shared.model.SensorStrength
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.data.repository.fakeBiometricSettingsRepository
+import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository
+import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DeviceEntryBiometricsAllowedInteractorTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+ private val underTest = kosmos.deviceEntryBiometricsAllowedInteractor
+
+ @Test
+ fun isFingerprintAuthCurrentlyAllowed_true() =
+ testScope.runTest {
+ val fpAllowed by collectLastValue(underTest.isFingerprintAuthCurrentlyAllowed)
+
+ // WHEN: not locked out, no face sensor, no strong auth requirements
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setLockedOut(false)
+ kosmos.fakeFacePropertyRepository.setSensorInfo(null)
+ kosmos.fakeBiometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(true)
+
+ // THEN fp is allowed
+ assertThat(fpAllowed).isTrue()
+ }
+
+ @Test
+ fun isFingerprintAuthCurrentlyAllowed_strongFaceLockedOut() =
+ testScope.runTest {
+ val fpAllowed by collectLastValue(underTest.isFingerprintAuthCurrentlyAllowed)
+
+ // WHEN: not locked out, face is strong & locked out, no strong auth requirements
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setLockedOut(false)
+ kosmos.fakeFacePropertyRepository.setSensorInfo(
+ FaceSensorInfo(
+ id = 0,
+ strength = SensorStrength.STRONG,
+ )
+ )
+ kosmos.fakeDeviceEntryFaceAuthRepository.setLockedOut(true)
+ kosmos.fakeBiometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(true)
+
+ // THEN fp is NOT allowed
+ assertThat(fpAllowed).isFalse()
+ }
+
+ @Test
+ fun isFingerprintAuthCurrentlyAllowed_convenienceFaceLockedOut() =
+ testScope.runTest {
+ val fpAllowed by collectLastValue(underTest.isFingerprintAuthCurrentlyAllowed)
+
+ // WHEN: not locked out, face is convenience & locked out, no strong auth requirements
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setLockedOut(false)
+ kosmos.fakeFacePropertyRepository.setSensorInfo(
+ FaceSensorInfo(
+ id = 0,
+ strength = SensorStrength.CONVENIENCE,
+ )
+ )
+ kosmos.fakeDeviceEntryFaceAuthRepository.setLockedOut(true)
+ kosmos.fakeBiometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(true)
+
+ // THEN fp is allowed
+ assertThat(fpAllowed).isTrue()
+ }
+
+ @Test
+ fun isFingerprintAuthCurrentlyAllowed_primaryAuthRequired() =
+ testScope.runTest {
+ val fpAllowed by collectLastValue(underTest.isFingerprintAuthCurrentlyAllowed)
+
+ // WHEN: not locked out, no face sensor, no strong auth requirements
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setLockedOut(false)
+ kosmos.fakeBiometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(false)
+
+ // THEN fp is NOT allowed
+ assertThat(fpAllowed).isFalse()
+ }
+
+ @Test
+ fun isFingerprintAuthCurrentlyAllowedOnBouncer_sfps() =
+ testScope.runTest {
+ val fpAllowedOnBouncer by
+ collectLastValue(underTest.isFingerprintCurrentlyAllowedOnBouncer)
+
+ // GIVEN fingerprint is generally allowed
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setLockedOut(false)
+ kosmos.fakeBiometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(true)
+
+ // WHEN side fps
+ kosmos.fakeFingerprintPropertyRepository.supportsSideFps()
+
+ // THEN fp is allowed on the primary bouncer
+ assertThat(fpAllowedOnBouncer).isTrue()
+ }
+
+ @Test
+ fun isFingerprintAuthCurrentlyAllowedOnBouncer_rearFps() =
+ testScope.runTest {
+ val fpAllowedOnBouncer by
+ collectLastValue(underTest.isFingerprintCurrentlyAllowedOnBouncer)
+
+ // GIVEN fingerprint is generally allowed
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setLockedOut(false)
+ kosmos.fakeBiometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(true)
+
+ // WHEN rear fps
+ kosmos.fakeFingerprintPropertyRepository.supportsRearFps()
+
+ // THEN fp is allowed on the primary bouncer
+ assertThat(fpAllowedOnBouncer).isTrue()
+ }
+
+ @Test
+ fun isFingerprintAuthCurrentlyAllowedOnBouncer_udfps() =
+ testScope.runTest {
+ val fpAllowedOnBouncer by
+ collectLastValue(underTest.isFingerprintCurrentlyAllowedOnBouncer)
+
+ // GIVEN fp is generally allowed
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setLockedOut(false)
+ kosmos.fakeBiometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(true)
+
+ // WHEN UDFPS
+ kosmos.fakeFingerprintPropertyRepository.supportsUdfps()
+
+ // THEN fp is never allowed on the primary bouncer
+ assertThat(fpAllowedOnBouncer).isFalse()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
index aa5edae..86da203 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
@@ -42,15 +42,22 @@
import static org.mockito.Mockito.when;
import android.content.Intent;
+import android.hardware.display.DisplayManager;
import android.os.PowerManager;
import android.os.UserHandle;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.provider.Settings;
+import android.view.Display;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.internal.display.BrightnessSynchronizer;
+import com.android.server.display.feature.flags.Flags;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.policy.DevicePostureController;
@@ -62,6 +69,7 @@
import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -74,10 +82,15 @@
@RunWith(AndroidJUnit4.class)
public class DozeScreenBrightnessTest extends SysuiTestCase {
- private static final int DEFAULT_BRIGHTNESS = 10;
- private static final int DIM_BRIGHTNESS = 1;
- private static final int[] SENSOR_TO_BRIGHTNESS = new int[]{-1, 1, 2, 3, 4};
+ private static final int DEFAULT_BRIGHTNESS_INT = 10;
+ private static final float DEFAULT_BRIGHTNESS_FLOAT = 0.1f;
+ private static final int DIM_BRIGHTNESS_INT = 1;
+ private static final float DIM_BRIGHTNESS_FLOAT = 0.05f;
+ private static final int[] SENSOR_TO_BRIGHTNESS_INT = new int[]{-1, 1, 2, 3, 4};
+ private static final float[] SENSOR_TO_BRIGHTNESS_FLOAT =
+ new float[]{-1, 0.01f, 0.05f, 0.7f, 0.1f};
private static final int[] SENSOR_TO_OPACITY = new int[]{-1, 10, 0, 0, 0};
+ private static final float DELTA = BrightnessSynchronizer.EPSILON;
private DozeServiceFake mServiceFake;
private FakeSensorManager.FakeGenericSensor mSensor;
@@ -91,23 +104,28 @@
@Mock
DozeParameters mDozeParameters;
@Mock
- DockManager mDockManager;
- @Mock
DevicePostureController mDevicePostureController;
@Mock
DozeLog mDozeLog;
@Mock
SystemSettings mSystemSettings;
- private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
- private FakeThreadFactory mFakeThreadFactory = new FakeThreadFactory(mFakeExecutor);
+ @Mock
+ DisplayManager mDisplayManager;
+ private final FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
+ private final FakeThreadFactory mFakeThreadFactory = new FakeThreadFactory(mFakeExecutor);
private DozeScreenBrightness mScreen;
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
when(mSystemSettings.getIntForUser(eq(Settings.System.SCREEN_BRIGHTNESS), anyInt(),
- eq(UserHandle.USER_CURRENT))).thenReturn(DEFAULT_BRIGHTNESS);
+ eq(UserHandle.USER_CURRENT))).thenReturn(PowerManager.BRIGHTNESS_ON);
+ when(mDisplayManager.getBrightness(Display.DEFAULT_DISPLAY))
+ .thenReturn(PowerManager.BRIGHTNESS_MAX);
doAnswer(invocation -> {
((Runnable) invocation.getArgument(0)).run();
return null;
@@ -117,9 +135,14 @@
mSensorManager = new AsyncSensorManager(fakeSensorManager, mFakeThreadFactory, null);
mAlwaysOnDisplayPolicy = new AlwaysOnDisplayPolicy(mContext);
- mAlwaysOnDisplayPolicy.defaultDozeBrightness = DEFAULT_BRIGHTNESS;
- mAlwaysOnDisplayPolicy.screenBrightnessArray = SENSOR_TO_BRIGHTNESS;
- mAlwaysOnDisplayPolicy.dimBrightness = DIM_BRIGHTNESS;
+ mAlwaysOnDisplayPolicy.defaultDozeBrightness = DEFAULT_BRIGHTNESS_INT;
+ when(mDisplayManager.getDefaultDozeBrightness(Display.DEFAULT_DISPLAY))
+ .thenReturn(DEFAULT_BRIGHTNESS_FLOAT);
+ mAlwaysOnDisplayPolicy.screenBrightnessArray = SENSOR_TO_BRIGHTNESS_INT;
+ when(mDisplayManager.getDozeBrightnessSensorValueToBrightness(Display.DEFAULT_DISPLAY))
+ .thenReturn(SENSOR_TO_BRIGHTNESS_FLOAT);
+ mAlwaysOnDisplayPolicy.dimBrightness = DIM_BRIGHTNESS_INT;
+ mAlwaysOnDisplayPolicy.dimBrightnessFloat = DIM_BRIGHTNESS_FLOAT;
mAlwaysOnDisplayPolicy.dimmingScrimArray = SENSOR_TO_OPACITY;
mSensor = fakeSensorManager.getFakeLightSensor();
mSensorInner = fakeSensorManager.getFakeLightSensor2();
@@ -135,19 +158,35 @@
mDozeParameters,
mDevicePostureController,
mDozeLog,
- mSystemSettings);
+ mSystemSettings,
+ mDisplayManager);
}
@Test
- public void testInitialize_setsScreenBrightnessToValidValue() throws Exception {
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void testInitialize_setsScreenBrightnessToValidValue_Int() {
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
- assertEquals(DEFAULT_BRIGHTNESS, mServiceFake.screenBrightness);
- assertTrue(mServiceFake.screenBrightness <= PowerManager.BRIGHTNESS_ON);
+ assertEquals(DEFAULT_BRIGHTNESS_INT, mServiceFake.screenBrightnessInt);
+ assertTrue(mServiceFake.screenBrightnessInt >= PowerManager.BRIGHTNESS_OFF + 1);
+ assertTrue(mServiceFake.screenBrightnessInt <= PowerManager.BRIGHTNESS_ON);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
}
@Test
- public void testAod_usesDebugValue() throws Exception {
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void testInitialize_setsScreenBrightnessToValidValue_Float() {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+
+ assertEquals(DEFAULT_BRIGHTNESS_FLOAT, mServiceFake.screenBrightnessFloat, DELTA);
+ assertTrue(mServiceFake.screenBrightnessFloat >= PowerManager.BRIGHTNESS_MIN);
+ assertTrue(mServiceFake.screenBrightnessFloat <= PowerManager.BRIGHTNESS_MAX);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void testAod_usesDebugValue_Int() {
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
waitForSensorManager();
@@ -157,11 +196,29 @@
mScreen.onReceive(mContext, intent);
mSensor.sendSensorEvent(3);
- assertEquals(1, mServiceFake.screenBrightness);
+ assertEquals(SENSOR_TO_BRIGHTNESS_INT[1], mServiceFake.screenBrightnessInt);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
}
@Test
- public void testAod_usesLightSensorRespectingUserSetting() {
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void testAod_usesDebugValue_Float() {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+ waitForSensorManager();
+
+ Intent intent = new Intent(DozeScreenBrightness.ACTION_AOD_BRIGHTNESS);
+ intent.putExtra(DozeScreenBrightness.BRIGHTNESS_BUCKET, 1);
+ mScreen.onReceive(mContext, intent);
+ mSensor.sendSensorEvent(3);
+
+ assertEquals(SENSOR_TO_BRIGHTNESS_FLOAT[1], mServiceFake.screenBrightnessFloat, DELTA);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void testAod_usesLightSensorRespectingUserSetting_Int() {
int maxBrightness = 3;
when(mSystemSettings.getIntForUser(eq(Settings.System.SCREEN_BRIGHTNESS), anyInt(),
eq(UserHandle.USER_CURRENT))).thenReturn(maxBrightness);
@@ -170,24 +227,59 @@
.thenReturn(Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
- assertEquals(maxBrightness, mServiceFake.screenBrightness);
+ assertEquals(maxBrightness, mServiceFake.screenBrightnessInt);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
}
@Test
- public void testAod_usesLightSensorNotClampingToAutoBrightnessValue() {
- int maxBrightness = 3;
- when(mSystemSettings.getIntForUser(eq(Settings.System.SCREEN_BRIGHTNESS), anyInt(),
- eq(UserHandle.USER_CURRENT))).thenReturn(maxBrightness);
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void testAod_usesLightSensorRespectingUserSetting_Float() {
+ float maxBrightness = DEFAULT_BRIGHTNESS_FLOAT / 2;
+ when(mDisplayManager.getBrightness(Display.DEFAULT_DISPLAY)).thenReturn(maxBrightness);
+ when(mSystemSettings.getIntForUser(eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
+ eq(UserHandle.USER_CURRENT)))
+ .thenReturn(Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
+
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ assertEquals(maxBrightness, mServiceFake.screenBrightnessFloat, DELTA);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void initialBrightness_clampsToAutoBrightnessValue_Float() {
+ float maxBrightnessFromAutoBrightness = DEFAULT_BRIGHTNESS_FLOAT / 2;
+ when(mDisplayManager.getBrightness(Display.DEFAULT_DISPLAY)).thenReturn(
+ maxBrightnessFromAutoBrightness
+ );
when(mSystemSettings.getIntForUser(eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
eq(UserHandle.USER_CURRENT)))
.thenReturn(Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
- assertEquals(DEFAULT_BRIGHTNESS, mServiceFake.screenBrightness);
+ assertEquals(maxBrightnessFromAutoBrightness, mServiceFake.screenBrightnessFloat,
+ DELTA);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
}
@Test
- public void doze_doesNotUseLightSensor() {
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void initialBrightness_clampsToAutoBrightnessValue_Int() {
+ int maxBrightnessFromAutoBrightness = DEFAULT_BRIGHTNESS_INT / 2;
+ when(mSystemSettings.getIntForUser(eq(Settings.System.SCREEN_BRIGHTNESS), anyInt(),
+ eq(UserHandle.USER_CURRENT))).thenReturn(maxBrightnessFromAutoBrightness);
+ when(mSystemSettings.getIntForUser(eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
+ eq(UserHandle.USER_CURRENT)))
+ .thenReturn(Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
+
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ assertEquals(maxBrightnessFromAutoBrightness, mServiceFake.screenBrightnessInt);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void doze_doesNotUseLightSensor_Int() {
// GIVEN the device is DOZE and the display state changes to ON
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE);
@@ -197,12 +289,31 @@
mSensor.sendSensorEvent(3);
// THEN brightness is NOT changed, it's set to the default brightness
- assertNotSame(3, mServiceFake.screenBrightness);
- assertEquals(DEFAULT_BRIGHTNESS, mServiceFake.screenBrightness);
+ assertNotSame(SENSOR_TO_BRIGHTNESS_INT[3], mServiceFake.screenBrightnessInt);
+ assertEquals(DEFAULT_BRIGHTNESS_INT, mServiceFake.screenBrightnessInt);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
}
@Test
- public void dozeSuspendTriggers_doesNotUseLightSensor() {
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void doze_doesNotUseLightSensor_Float() {
+ // GIVEN the device is DOZE and the display state changes to ON
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE);
+ waitForSensorManager();
+
+ // WHEN new sensor event sent
+ mSensor.sendSensorEvent(3);
+
+ // THEN brightness is NOT changed, it's set to the default brightness
+ assertNotSame(SENSOR_TO_BRIGHTNESS_FLOAT[3], mServiceFake.screenBrightnessInt);
+ assertEquals(DEFAULT_BRIGHTNESS_FLOAT, mServiceFake.screenBrightnessFloat, DELTA);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void dozeSuspendTriggers_doesNotUseLightSensor_Int() {
// GIVEN the device is DOZE and the display state changes to ON
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_SUSPEND_TRIGGERS);
@@ -212,12 +323,31 @@
mSensor.sendSensorEvent(3);
// THEN brightness is NOT changed, it's set to the default brightness
- assertNotSame(3, mServiceFake.screenBrightness);
- assertEquals(DEFAULT_BRIGHTNESS, mServiceFake.screenBrightness);
+ assertNotSame(SENSOR_TO_BRIGHTNESS_INT[3], mServiceFake.screenBrightnessInt);
+ assertEquals(DEFAULT_BRIGHTNESS_INT, mServiceFake.screenBrightnessInt);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
}
@Test
- public void aod_usesLightSensor() {
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void dozeSuspendTriggers_doesNotUseLightSensor_Float() {
+ // GIVEN the device is DOZE and the display state changes to ON
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_SUSPEND_TRIGGERS);
+ waitForSensorManager();
+
+ // WHEN new sensor event sent
+ mSensor.sendSensorEvent(3);
+
+ // THEN brightness is NOT changed, it's set to the default brightness
+ assertNotSame(SENSOR_TO_BRIGHTNESS_FLOAT[3], mServiceFake.screenBrightnessFloat);
+ assertEquals(DEFAULT_BRIGHTNESS_FLOAT, mServiceFake.screenBrightnessFloat, DELTA);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void aod_usesLightSensor_Int() {
// GIVEN the device is DOZE_AOD and the display state changes to ON
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
@@ -227,11 +357,77 @@
mSensor.sendSensorEvent(3);
// THEN brightness is updated
- assertEquals(3, mServiceFake.screenBrightness);
+ assertEquals(SENSOR_TO_BRIGHTNESS_INT[3], mServiceFake.screenBrightnessInt);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
}
@Test
- public void docked_usesLightSensor() {
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void aod_usesLightSensor_Float() {
+ // GIVEN the device is DOZE_AOD and the display state changes to ON
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+ waitForSensorManager();
+
+ // WHEN new sensor event sent
+ mSensor.sendSensorEvent(3);
+
+ // THEN brightness is updated
+ assertEquals(SENSOR_TO_BRIGHTNESS_FLOAT[3], mServiceFake.screenBrightnessFloat, DELTA);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void lightSensorChangesInAod_doesNotClampToAutoBrightnessValue_Float() {
+ // GIVEN auto brightness reports low brightness
+ float maxBrightnessFromAutoBrightness = DEFAULT_BRIGHTNESS_FLOAT / 2;
+ when(mDisplayManager.getBrightness(Display.DEFAULT_DISPLAY))
+ .thenReturn(maxBrightnessFromAutoBrightness);
+ when(mSystemSettings.getIntForUser(eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
+ eq(UserHandle.USER_CURRENT)))
+ .thenReturn(Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
+
+ // GIVEN the device is DOZE_AOD and the display state changes to ON
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+ waitForSensorManager();
+
+ // WHEN new sensor event sent
+ mSensor.sendSensorEvent(3);
+
+ // THEN brightness is updated
+ assertEquals(SENSOR_TO_BRIGHTNESS_FLOAT[3], mServiceFake.screenBrightnessFloat, DELTA);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void lightSensorChangesInAod_doesNotClampToAutoBrightnessValue_Int() {
+ // GIVEN auto brightness reports low brightness
+ int maxBrightnessFromAutoBrightness = 1;
+ when(mSystemSettings.getIntForUser(eq(Settings.System.SCREEN_BRIGHTNESS), anyInt(),
+ eq(UserHandle.USER_CURRENT))).thenReturn(maxBrightnessFromAutoBrightness);
+ when(mSystemSettings.getIntForUser(eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
+ eq(UserHandle.USER_CURRENT)))
+ .thenReturn(Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
+
+ // GIVEN the device is DOZE_AOD and the display state changes to ON
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+ waitForSensorManager();
+
+ // WHEN new sensor event sent
+ mSensor.sendSensorEvent(3);
+
+ // THEN brightness is updated
+ assertEquals(SENSOR_TO_BRIGHTNESS_INT[3], mServiceFake.screenBrightnessInt);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void docked_usesLightSensor_Int() {
// GIVEN the device is docked and the display state changes to ON
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
@@ -242,11 +438,29 @@
mSensor.sendSensorEvent(3);
// THEN brightness is updated
- assertEquals(3, mServiceFake.screenBrightness);
+ assertEquals(SENSOR_TO_BRIGHTNESS_INT[3], mServiceFake.screenBrightnessInt);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
}
@Test
- public void testPulsing_withoutLightSensor_setsAoDDimmingScrimTransparent() throws Exception {
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void docked_usesLightSensor_Float() {
+ // GIVEN the device is docked and the display state changes to ON
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+ mScreen.transitionTo(DOZE_AOD, DOZE_AOD_DOCKED);
+ waitForSensorManager();
+
+ // WHEN new sensor event sent
+ mSensor.sendSensorEvent(3);
+
+ // THEN brightness is updated
+ assertEquals(SENSOR_TO_BRIGHTNESS_FLOAT[3], mServiceFake.screenBrightnessFloat, DELTA);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+ }
+
+ @Test
+ public void testPulsing_withoutLightSensor_setsAoDDimmingScrimTransparent() {
mScreen = new DozeScreenBrightness(
mContext,
mServiceFake,
@@ -258,7 +472,8 @@
mDozeParameters,
mDevicePostureController,
mDozeLog,
- mSystemSettings);
+ mSystemSettings,
+ mDisplayManager);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE);
reset(mDozeHost);
@@ -269,7 +484,8 @@
}
@Test
- public void testScreenOffAfterPulsing_pausesLightSensor() throws Exception {
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void testScreenOffAfterPulsing_pausesLightSensor_Int() {
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE);
mScreen.transitionTo(DOZE, DOZE_REQUEST_PULSE);
@@ -280,11 +496,29 @@
mSensor.sendSensorEvent(1);
- assertEquals(DEFAULT_BRIGHTNESS, mServiceFake.screenBrightness);
+ assertEquals(DEFAULT_BRIGHTNESS_INT, mServiceFake.screenBrightnessInt);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
}
@Test
- public void testNullSensor() throws Exception {
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void testScreenOffAfterPulsing_pausesLightSensor_Float() {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE);
+ mScreen.transitionTo(DOZE, DOZE_REQUEST_PULSE);
+ mScreen.transitionTo(DOZE_REQUEST_PULSE, DOZE_PULSING);
+ mScreen.transitionTo(DOZE_PULSING, DOZE_PULSE_DONE);
+ mScreen.transitionTo(DOZE_PULSE_DONE, DOZE);
+ waitForSensorManager();
+
+ mSensor.sendSensorEvent(1);
+
+ assertEquals(DEFAULT_BRIGHTNESS_FLOAT, mServiceFake.screenBrightnessFloat, DELTA);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+ }
+
+ @Test
+ public void testNullSensor() {
mScreen = new DozeScreenBrightness(
mContext,
mServiceFake,
@@ -296,7 +530,8 @@
mDozeParameters,
mDevicePostureController,
mDozeLog,
- mSystemSettings);
+ mSystemSettings,
+ mDisplayManager);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
@@ -305,7 +540,8 @@
}
@Test
- public void testSensorsSupportPostures_closed() throws Exception {
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void testSensorsSupportPostures_closed_Int() {
// GIVEN the device is CLOSED
when(mDevicePostureController.getDevicePosture()).thenReturn(
DevicePostureController.DEVICE_POSTURE_CLOSED);
@@ -328,7 +564,8 @@
mDozeParameters,
mDevicePostureController,
mDozeLog,
- mSystemSettings);
+ mSystemSettings,
+ mDisplayManager);
// GIVEN the device is in AOD
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
@@ -340,11 +577,56 @@
mSensorInner.sendSensorEvent(4); // OPENED sensor
// THEN brightness is updated according to the sensor for CLOSED
- assertEquals(3, mServiceFake.screenBrightness);
+ assertEquals(SENSOR_TO_BRIGHTNESS_INT[3], mServiceFake.screenBrightnessInt);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
}
@Test
- public void testSensorsSupportPostures_open() throws Exception {
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void testSensorsSupportPostures_closed_Float() {
+ // GIVEN the device is CLOSED
+ when(mDevicePostureController.getDevicePosture()).thenReturn(
+ DevicePostureController.DEVICE_POSTURE_CLOSED);
+
+ // GIVEN closed and opened postures use different light sensors
+ mScreen = new DozeScreenBrightness(
+ mContext,
+ mServiceFake,
+ mSensorManager,
+ new Optional[]{
+ Optional.empty() /* unknown */,
+ Optional.of(mSensor.getSensor()) /* closed */,
+ Optional.of(mSensorInner.getSensor()) /* half-opened */,
+ Optional.of(mSensorInner.getSensor()) /* opened */,
+ Optional.empty() /* flipped */
+ },
+ mDozeHost, null /* handler */,
+ mAlwaysOnDisplayPolicy,
+ mWakefulnessLifecycle,
+ mDozeParameters,
+ mDevicePostureController,
+ mDozeLog,
+ mSystemSettings,
+ mDisplayManager);
+
+ // GIVEN the device is in AOD
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+ waitForSensorManager();
+
+ // WHEN new different events are sent from the inner and outer sensors
+ mSensor.sendSensorEvent(3); // CLOSED sensor
+ mSensorInner.sendSensorEvent(4); // OPENED sensor
+
+ // THEN brightness is updated according to the sensor for CLOSED
+ assertEquals(SENSOR_TO_BRIGHTNESS_FLOAT[3], mServiceFake.screenBrightnessFloat,
+ DELTA);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void testSensorsSupportPostures_open_Int() {
// GIVEN the device is OPENED
when(mDevicePostureController.getDevicePosture()).thenReturn(
DevicePostureController.DEVICE_POSTURE_OPENED);
@@ -367,7 +649,8 @@
mDozeParameters,
mDevicePostureController,
mDozeLog,
- mSystemSettings);
+ mSystemSettings,
+ mDisplayManager);
// GIVEN device is in AOD
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
@@ -379,11 +662,55 @@
mSensor.sendSensorEvent(3); // CLOSED sensor
// THEN brightness is updated according to the sensor for OPENED
- assertEquals(4, mServiceFake.screenBrightness);
+ assertEquals(SENSOR_TO_BRIGHTNESS_INT[4], mServiceFake.screenBrightnessInt);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
}
@Test
- public void testSensorsSupportPostures_swapPostures() throws Exception {
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void testSensorsSupportPostures_open_Float() {
+ // GIVEN the device is OPENED
+ when(mDevicePostureController.getDevicePosture()).thenReturn(
+ DevicePostureController.DEVICE_POSTURE_OPENED);
+
+ // GIVEN closed and opened postures use different light sensors
+ mScreen = new DozeScreenBrightness(
+ mContext,
+ mServiceFake,
+ mSensorManager,
+ new Optional[]{
+ Optional.empty() /* unknown */,
+ Optional.of(mSensor.getSensor()) /* closed */,
+ Optional.of(mSensorInner.getSensor()) /* half-opened */,
+ Optional.of(mSensorInner.getSensor()) /* opened */,
+ Optional.empty() /* flipped */
+ },
+ mDozeHost, null /* handler */,
+ mAlwaysOnDisplayPolicy,
+ mWakefulnessLifecycle,
+ mDozeParameters,
+ mDevicePostureController,
+ mDozeLog,
+ mSystemSettings,
+ mDisplayManager);
+
+ // GIVEN device is in AOD
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+ waitForSensorManager();
+
+ // WHEN new different events are sent from the inner and outer sensors
+ mSensorInner.sendSensorEvent(4); // OPENED sensor
+ mSensor.sendSensorEvent(3); // CLOSED sensor
+
+ // THEN brightness is updated according to the sensor for OPENED
+ assertEquals(SENSOR_TO_BRIGHTNESS_FLOAT[4], mServiceFake.screenBrightnessFloat, DELTA);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void testSensorsSupportPostures_swapPostures_Int() {
ArgumentCaptor<DevicePostureController.Callback> postureCallbackCaptor =
ArgumentCaptor.forClass(DevicePostureController.Callback.class);
reset(mDevicePostureController);
@@ -410,7 +737,8 @@
mDozeParameters,
mDevicePostureController,
mDozeLog,
- mSystemSettings);
+ mSystemSettings,
+ mDisplayManager);
verify(mDevicePostureController).addCallback(postureCallbackCaptor.capture());
// GIVEN device is in AOD
@@ -428,11 +756,65 @@
mSensorInner.sendSensorEvent(4); // OPENED sensor
// THEN brightness is updated according to the sensor for CLOSED
- assertEquals(3, mServiceFake.screenBrightness);
+ assertEquals(SENSOR_TO_BRIGHTNESS_INT[3], mServiceFake.screenBrightnessInt);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
}
@Test
- public void testNoBrightnessDeliveredAfterFinish() throws Exception {
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void testSensorsSupportPostures_swapPostures_Float() {
+ ArgumentCaptor<DevicePostureController.Callback> postureCallbackCaptor =
+ ArgumentCaptor.forClass(DevicePostureController.Callback.class);
+ reset(mDevicePostureController);
+
+ // GIVEN the device starts up AOD OPENED
+ when(mDevicePostureController.getDevicePosture()).thenReturn(
+ DevicePostureController.DEVICE_POSTURE_OPENED);
+
+ // GIVEN closed and opened postures use different light sensors
+ mScreen = new DozeScreenBrightness(
+ mContext,
+ mServiceFake,
+ mSensorManager,
+ new Optional[]{
+ Optional.empty() /* unknown */,
+ Optional.of(mSensor.getSensor()) /* closed */,
+ Optional.of(mSensorInner.getSensor()) /* half-opened */,
+ Optional.of(mSensorInner.getSensor()) /* opened */,
+ Optional.empty() /* flipped */
+ },
+ mDozeHost, null /* handler */,
+ mAlwaysOnDisplayPolicy,
+ mWakefulnessLifecycle,
+ mDozeParameters,
+ mDevicePostureController,
+ mDozeLog,
+ mSystemSettings,
+ mDisplayManager);
+ verify(mDevicePostureController).addCallback(postureCallbackCaptor.capture());
+
+ // GIVEN device is in AOD
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+ waitForSensorManager();
+
+ // WHEN the posture changes to CLOSED
+ postureCallbackCaptor.getValue().onPostureChanged(
+ DevicePostureController.DEVICE_POSTURE_CLOSED);
+ waitForSensorManager();
+
+ // WHEN new different events are sent from the inner and outer sensors
+ mSensor.sendSensorEvent(3); // CLOSED sensor
+ mSensorInner.sendSensorEvent(4); // OPENED sensor
+
+ // THEN brightness is updated according to the sensor for CLOSED
+ assertEquals(SENSOR_TO_BRIGHTNESS_FLOAT[3], mServiceFake.screenBrightnessFloat, DELTA);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void testNoBrightnessDeliveredAfterFinish_Int() {
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
mScreen.transitionTo(DOZE_AOD, FINISH);
@@ -440,11 +822,27 @@
mSensor.sendSensorEvent(1);
- assertNotEquals(1, mServiceFake.screenBrightness);
+ assertNotEquals(SENSOR_TO_BRIGHTNESS_INT[1], mServiceFake.screenBrightnessInt);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
}
@Test
- public void testNonPositiveBrightness_keepsPreviousBrightnessAndScrim() {
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void testNoBrightnessDeliveredAfterFinish_Float() {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+ mScreen.transitionTo(DOZE_AOD, FINISH);
+ waitForSensorManager();
+
+ mSensor.sendSensorEvent(1);
+
+ assertNotEquals(SENSOR_TO_BRIGHTNESS_FLOAT[1], mServiceFake.screenBrightnessFloat);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void testNonPositiveBrightness_keepsPreviousBrightnessAndScrim_Int() {
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
waitForSensorManager();
@@ -452,7 +850,23 @@
mSensor.sendSensorEvent(1);
mSensor.sendSensorEvent(0);
- assertEquals(1, mServiceFake.screenBrightness);
+ assertEquals(SENSOR_TO_BRIGHTNESS_INT[1], mServiceFake.screenBrightnessInt);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
+ verify(mDozeHost).setAodDimmingScrim(eq(10f / 255f));
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void testNonPositiveBrightness_keepsPreviousBrightnessAndScrim_Float() {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+ waitForSensorManager();
+
+ mSensor.sendSensorEvent(1);
+ mSensor.sendSensorEvent(0);
+
+ assertEquals(SENSOR_TO_BRIGHTNESS_FLOAT[1], mServiceFake.screenBrightnessFloat, DELTA);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
verify(mDozeHost).setAodDimmingScrim(eq(10f / 255f));
}
@@ -473,7 +887,8 @@
}
@Test
- public void transitionToDoze_shouldClampBrightness_afterTimeout_clampsToDim() {
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void transitionToDoze_shouldClampBrightness_afterTimeout_clampsToDim_Int() {
when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(true);
@@ -482,15 +897,38 @@
// If we're dozing after a timeout, and playing the unlocked screen animation, we should
// stay at or below dim brightness, because the screen dims just before timeout.
- assertTrue(mServiceFake.screenBrightness <= DIM_BRIGHTNESS);
+ assertTrue(mServiceFake.screenBrightnessInt <= DIM_BRIGHTNESS_INT);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
// Once we transition to Doze, use the doze brightness
mScreen.transitionTo(INITIALIZED, DOZE);
- assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS);
+ assertEquals(mServiceFake.screenBrightnessInt, DEFAULT_BRIGHTNESS_INT);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
}
@Test
- public void transitionToDoze_shouldClampBrightness_notAfterTimeout_doesNotClampToDim() {
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void transitionToDoze_shouldClampBrightness_afterTimeout_clampsToDim_Float() {
+ when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
+ PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
+ when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(true);
+
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+
+ // If we're dozing after a timeout, and playing the unlocked screen animation, we should
+ // stay at or below dim brightness, because the screen dims just before timeout.
+ assertTrue(mServiceFake.screenBrightnessFloat <= DIM_BRIGHTNESS_FLOAT);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+
+ // Once we transition to Doze, use the doze brightness
+ mScreen.transitionTo(INITIALIZED, DOZE);
+ assertEquals(mServiceFake.screenBrightnessFloat, DEFAULT_BRIGHTNESS_FLOAT, DELTA);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void transitionToDoze_shouldClampBrightness_notAfterTimeout_doesNotClampToDim_Int() {
when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(true);
@@ -499,14 +937,36 @@
// If we're playing the unlocked screen off animation after a power button press, we should
// leave the brightness alone.
- assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS);
+ assertEquals(mServiceFake.screenBrightnessInt, DEFAULT_BRIGHTNESS_INT);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
mScreen.transitionTo(INITIALIZED, DOZE);
- assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS);
+ assertEquals(mServiceFake.screenBrightnessInt, DEFAULT_BRIGHTNESS_INT);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
}
@Test
- public void transitionToDoze_noClampBrightness_afterTimeout_noScreenOff_doesNotClampToDim() {
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void transitionToDoze_shouldClampBrightness_notAfterTimeout_doesNotClampToDim_Float() {
+ when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
+ PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
+ when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(true);
+
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+
+ // If we're playing the unlocked screen off animation after a power button press, we should
+ // leave the brightness alone.
+ assertEquals(mServiceFake.screenBrightnessFloat, DEFAULT_BRIGHTNESS_FLOAT, DELTA);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+
+ mScreen.transitionTo(INITIALIZED, DOZE);
+ assertEquals(mServiceFake.screenBrightnessFloat, DEFAULT_BRIGHTNESS_FLOAT, DELTA);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void transitionToDoze_noClamp_afterTimeout_noScreenOff_doesNotClampToDim_Int() {
when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(false);
@@ -515,11 +975,28 @@
mScreen.transitionTo(INITIALIZED, DOZE);
// If we aren't controlling the screen off animation, we should leave the brightness alone.
- assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS);
+ assertEquals(mServiceFake.screenBrightnessInt, DEFAULT_BRIGHTNESS_INT);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
}
@Test
- public void transitionToDoze_noClampBrightness_afterTimeout_clampsToDim() {
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void transitionToDoze_noClamp_afterTimeout_noScreenOff_doesNotClampToDim_Float() {
+ when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
+ PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
+ when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(false);
+
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE);
+
+ // If we aren't controlling the screen off animation, we should leave the brightness alone.
+ assertEquals(mServiceFake.screenBrightnessFloat, DEFAULT_BRIGHTNESS_FLOAT, DELTA);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void transitionToDoze_noClampBrightness_afterTimeout_clampsToDim_Int() {
when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
when(mWakefulnessLifecycle.getWakefulness()).thenReturn(
@@ -528,11 +1005,28 @@
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
- assertTrue(mServiceFake.screenBrightness <= DIM_BRIGHTNESS);
+ assertTrue(mServiceFake.screenBrightnessInt <= DIM_BRIGHTNESS_INT);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
}
@Test
- public void transitionToDoze_noClampBrigthness_notAfterTimeout_doesNotClampToDim() {
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void transitionToDoze_noClampBrightness_afterTimeout_clampsToDim_Float() {
+ when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
+ PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
+ when(mWakefulnessLifecycle.getWakefulness()).thenReturn(
+ WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP);
+ when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(false);
+
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+
+ assertTrue(mServiceFake.screenBrightnessFloat <= DIM_BRIGHTNESS_FLOAT);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void transitionToDoze_noClampBrigthness_notAfterTimeout_doesNotClampToDim_Int() {
when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
when(mWakefulnessLifecycle.getWakefulness()).thenReturn(
@@ -542,11 +1036,29 @@
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE);
- assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS);
+ assertEquals(mServiceFake.screenBrightnessInt, DEFAULT_BRIGHTNESS_INT);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
}
@Test
- public void transitionToAodPaused_lightSensorDisabled() {
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void transitionToDoze_noClampBrigthness_notAfterTimeout_doesNotClampToDim_Float() {
+ when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
+ PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
+ when(mWakefulnessLifecycle.getWakefulness()).thenReturn(
+ WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP);
+ when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(false);
+
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE);
+
+ assertEquals(mServiceFake.screenBrightnessFloat, DEFAULT_BRIGHTNESS_FLOAT, DELTA);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void transitionToAodPaused_lightSensorDisabled_Int() {
// GIVEN AOD
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
@@ -558,11 +1070,31 @@
// THEN new light events don't update brightness since the light sensor was unregistered
mSensor.sendSensorEvent(1);
- assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS);
+ assertEquals(mServiceFake.screenBrightnessInt, DEFAULT_BRIGHTNESS_INT);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
}
@Test
- public void transitionFromAodPausedToAod_lightSensorEnabled() {
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void transitionToAodPaused_lightSensorDisabled_Float() {
+ // GIVEN AOD
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+
+ // WHEN AOD is paused
+ mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING);
+ mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSED);
+ waitForSensorManager();
+
+ // THEN new light events don't update brightness since the light sensor was unregistered
+ mSensor.sendSensorEvent(1);
+ assertEquals(mServiceFake.screenBrightnessFloat, DEFAULT_BRIGHTNESS_FLOAT, DELTA);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void transitionFromAodPausedToAod_lightSensorEnabled_Int() {
// GIVEN AOD paused
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
@@ -577,7 +1109,54 @@
mSensor.sendSensorEvent(1);
// THEN aod brightness is updated
- assertEquals(mServiceFake.screenBrightness, 1);
+ assertEquals(SENSOR_TO_BRIGHTNESS_INT[1], mServiceFake.screenBrightnessInt);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void transitionFromAodPausedToAod_lightSensorEnabled_Float() {
+ // GIVEN AOD paused
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+ mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING);
+ mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSED);
+
+ // WHEN device transitions back to AOD
+ mScreen.transitionTo(DOZE_AOD_PAUSED, DOZE_AOD);
+ waitForSensorManager();
+
+ // WHEN there are brightness changes
+ mSensor.sendSensorEvent(1);
+
+ // THEN aod brightness is updated
+ assertEquals(SENSOR_TO_BRIGHTNESS_FLOAT[1], mServiceFake.screenBrightnessFloat, DELTA);
+ assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT)
+ public void fallBackToIntIfFloatBrightnessUndefined() {
+ when(mDisplayManager.getDozeBrightnessSensorValueToBrightness(Display.DEFAULT_DISPLAY))
+ .thenReturn(null);
+ mScreen = new DozeScreenBrightness(
+ mContext,
+ mServiceFake,
+ mSensorManager,
+ new Optional[]{Optional.of(mSensor.getSensor())},
+ mDozeHost,
+ null /* handler */,
+ mAlwaysOnDisplayPolicy,
+ mWakefulnessLifecycle,
+ mDozeParameters,
+ mDevicePostureController,
+ mDozeLog,
+ mSystemSettings,
+ mDisplayManager);
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+
+ assertEquals(DEFAULT_BRIGHTNESS_INT, mServiceFake.screenBrightnessInt);
+ assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat));
}
private void waitForSensorManager() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java
index 928b314..f55c2b7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java
@@ -30,7 +30,8 @@
public int screenState;
public boolean screenStateSet;
public boolean requestedWakeup;
- public int screenBrightness;
+ public int screenBrightnessInt;
+ public float screenBrightnessFloat;
public DozeServiceFake() {
reset();
@@ -54,7 +55,12 @@
@Override
public void setDozeScreenBrightness(int brightness) {
- screenBrightness = brightness;
+ screenBrightnessInt = brightness;
+ }
+
+ @Override
+ public void setDozeScreenBrightnessFloat(float brightness) {
+ screenBrightnessFloat = brightness;
}
public void reset() {
@@ -62,6 +68,7 @@
screenState = Display.STATE_UNKNOWN;
screenStateSet = false;
requestedWakeup = false;
- screenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
+ screenBrightnessInt = PowerManager.BRIGHTNESS_DEFAULT;
+ screenBrightnessFloat = PowerManager.BRIGHTNESS_INVALID_FLOAT;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 9de7528..e3a38a8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -272,6 +272,7 @@
mShadeWindowLogger,
() -> mSelectedUserInteractor,
mUserTracker,
+ mKosmos.getNotificationShadeWindowModel(),
mKosmos::getCommunalInteractor);
mFeatureFlags = new FakeFeatureFlags();
mSetFlagsRule.enableFlags(FLAG_REFACTOR_GET_CURRENT_USER);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
index 48a5df9..2af4d87 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
@@ -45,6 +45,7 @@
import java.math.RoundingMode
import java.util.UUID
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.dropWhile
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
@@ -332,10 +333,11 @@
}
@Test
- fun attemptTomanuallyUpdateTransitionWithInvalidUUIDthrowsException() {
- underTest.updateTransition(UUID.randomUUID(), 0f, TransitionState.RUNNING)
- assertThat(wtfHandler.failed).isTrue()
- }
+ fun attemptTomanuallyUpdateTransitionWithInvalidUUIDthrowsException() =
+ testScope.runTest {
+ underTest.updateTransition(UUID.randomUUID(), 0f, TransitionState.RUNNING)
+ assertThat(wtfHandler.failed).isTrue()
+ }
@Test
fun attemptToManuallyUpdateTransitionAfterFINISHEDstateThrowsException() =
@@ -414,6 +416,64 @@
)
}
+ @Test
+ fun simulateRaceConditionIsProcessedInOrderUsingUpdateTransition() =
+ testScope.runTest {
+ val ktr = KeyguardTransitionRepositoryImpl(kosmos.testDispatcher)
+ val steps by collectValues(ktr.transitions.dropWhile { step -> step.from == OFF })
+
+ // Begin a manual transition
+ val info1 = TransitionInfo(OWNER_NAME, AOD, LOCKSCREEN, animator = null)
+ launch {
+ ktr.forceDelayForRaceConditionTest = false
+ val uuid = ktr.startTransition(info1)
+
+ // Pause here to allow another transition to start
+ delay(20)
+
+ // Attempt to send an update, which should fail
+ ktr.updateTransition(uuid!!, 0.5f, TransitionState.RUNNING)
+ }
+
+ // Now start another transition, which should acquire the preempt the first
+ val info2 = TransitionInfo(OWNER_NAME, LOCKSCREEN, OCCLUDED, animator = null)
+ launch {
+ delay(10)
+ ktr.forceDelayForRaceConditionTest = true
+ ktr.startTransition(info2)
+ }
+
+ runCurrent()
+
+ // Manual transition has started
+ assertThat(steps[0])
+ .isEqualTo(
+ TransitionStep(info1.from, info1.to, 0f, TransitionState.STARTED, OWNER_NAME)
+ )
+
+ // The second transition has requested to start, and grabbed the mutex. But it is
+ // delayed
+ advanceTimeBy(15L)
+
+ // Advancing another 10ms should now trigger the first transition to request an update,
+ // which should not happen as the second transition has the mutex
+ advanceTimeBy(10L)
+
+ // Finally, advance past the delay in the second transition so it can run
+ advanceTimeBy(50L)
+
+ assertThat(steps[1])
+ .isEqualTo(
+ TransitionStep(info1.from, info1.to, 0f, TransitionState.CANCELED, OWNER_NAME)
+ )
+ assertThat(steps[2])
+ .isEqualTo(
+ TransitionStep(info2.from, info2.to, 0f, TransitionState.STARTED, OWNER_NAME)
+ )
+
+ assertThat(steps.size).isEqualTo(3)
+ }
+
private fun listWithStep(
step: BigDecimal,
start: BigDecimal = BigDecimal.ZERO,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt
index a8271c1..2a2a82d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt
@@ -31,8 +31,8 @@
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryBiometricsAllowedInteractor
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFingerprintAuthInteractor
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
@@ -112,7 +112,7 @@
biometricSettingsRepository,
FakeSystemClock(),
keyguardUpdateMonitor,
- { mock(DeviceEntryFingerprintAuthInteractor::class.java) },
+ { mock(DeviceEntryBiometricsAllowedInteractor::class.java) },
{ mock(KeyguardInteractor::class.java) },
{ mock(KeyguardTransitionInteractor::class.java) },
{ kosmos.sceneInteractor },
diff --git a/packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt
index afab250..d3409c7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt
@@ -24,12 +24,14 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.Assert
-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.DisposableHandle
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.awaitCancellation
+import kotlinx.coroutines.launch
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.resetMain
@@ -47,6 +49,8 @@
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit
+import org.mockito.kotlin.KArgumentCaptor
+import org.mockito.kotlin.argumentCaptor
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@@ -96,6 +100,14 @@
}
@Test(expected = IllegalStateException::class)
+ fun repeatWhenAttachedToWindow_enforcesMainThread() =
+ testScope.runTest {
+ Assert.setTestThread(null)
+
+ view.repeatWhenAttachedToWindow {}
+ }
+
+ @Test(expected = IllegalStateException::class)
fun repeatWhenAttached_disposeEnforcesMainThread() =
testScope.runTest {
val disposableHandle = repeatWhenAttached()
@@ -120,6 +132,58 @@
}
@Test
+ fun repeatWhenAttachedToWindow_viewAlreadyAttached_immediatelyRunsBlock() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(true)
+
+ var innerJob: Job? = null
+ backgroundScope.launch {
+ view.repeatWhenAttachedToWindow { innerJob = launch { awaitCancellation() } }
+ }
+ runCurrent()
+
+ assertThat(innerJob?.isActive).isEqualTo(true)
+ }
+
+ @Test
+ fun repeatWhenAttachedToWindow_viewStartsDetached_runsBlockWhenAttached() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(false)
+ var innerJob: Job? = null
+ backgroundScope.launch {
+ view.repeatWhenAttachedToWindow { innerJob = launch { awaitCancellation() } }
+ }
+ runCurrent()
+
+ assertThat(innerJob?.isActive).isNotEqualTo(true)
+
+ whenever(view.isAttachedToWindow).thenReturn(true)
+ attachListeners.last().onViewAttachedToWindow(view)
+ runCurrent()
+
+ assertThat(innerJob?.isActive).isEqualTo(true)
+ }
+
+ @Test
+ fun repeatWhenAttachedToWindow_viewGetsDetached_cancelsBlock() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(true)
+ var innerJob: Job? = null
+ backgroundScope.launch {
+ view.repeatWhenAttachedToWindow { innerJob = launch { awaitCancellation() } }
+ }
+ runCurrent()
+
+ assertThat(innerJob?.isActive).isEqualTo(true)
+
+ whenever(view.isAttachedToWindow).thenReturn(false)
+ attachListeners.last().onViewDetachedFromWindow(view)
+ runCurrent()
+
+ assertThat(innerJob?.isActive).isNotEqualTo(true)
+ }
+
+ @Test
fun repeatWhenAttached_viewAlreadyAttached_immediatelyRunsBlock() =
testScope.runTest {
whenever(view.isAttachedToWindow).thenReturn(true)
@@ -145,6 +209,65 @@
}
@Test
+ fun repeatWhenWindowIsVisible_startsAlreadyVisible_immediatelyRunsBlock() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(true)
+ whenever(view.windowVisibility).thenReturn(View.VISIBLE)
+
+ var innerJob: Job? = null
+ backgroundScope.launch {
+ view.repeatWhenWindowIsVisible { innerJob = launch { awaitCancellation() } }
+ }
+ runCurrent()
+
+ assertThat(innerJob?.isActive).isEqualTo(true)
+ }
+
+ @Test
+ fun repeatWhenWindowIsVisible_startsInvisible_runsBlockWhenVisible() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(true)
+ whenever(view.windowVisibility).thenReturn(View.INVISIBLE)
+
+ var innerJob: Job? = null
+ backgroundScope.launch {
+ view.repeatWhenWindowIsVisible { innerJob = launch { awaitCancellation() } }
+ }
+ runCurrent()
+
+ assertThat(innerJob?.isActive).isNotEqualTo(true)
+
+ whenever(view.windowVisibility).thenReturn(View.VISIBLE)
+ argCaptor { verify(viewTreeObserver).addOnWindowVisibilityChangeListener(capture()) }
+ .forEach { it.onWindowVisibilityChanged(View.VISIBLE) }
+ runCurrent()
+
+ assertThat(innerJob?.isActive).isEqualTo(true)
+ }
+
+ @Test
+ fun repeatWhenWindowIsVisible_becomesInvisible_cancelsBlock() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(true)
+ whenever(view.windowVisibility).thenReturn(View.VISIBLE)
+
+ var innerJob: Job? = null
+ backgroundScope.launch {
+ view.repeatWhenWindowIsVisible { innerJob = launch { awaitCancellation() } }
+ }
+ runCurrent()
+
+ assertThat(innerJob?.isActive).isEqualTo(true)
+
+ whenever(view.windowVisibility).thenReturn(View.INVISIBLE)
+ argCaptor { verify(viewTreeObserver).addOnWindowVisibilityChangeListener(capture()) }
+ .forEach { it.onWindowVisibilityChanged(View.INVISIBLE) }
+ runCurrent()
+
+ assertThat(innerJob?.isActive).isNotEqualTo(true)
+ }
+
+ @Test
fun repeatWhenAttached_startsWithFocusButInvisible_CREATED() =
testScope.runTest {
whenever(view.isAttachedToWindow).thenReturn(true)
@@ -172,6 +295,69 @@
}
@Test
+ fun repeatWhenWindowHasFocus_startsWithFocus_immediatelyRunsBlock() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(true)
+ whenever(view.windowVisibility).thenReturn(View.VISIBLE)
+ whenever(view.hasWindowFocus()).thenReturn(true)
+
+ var innerJob: Job? = null
+ backgroundScope.launch {
+ view.repeatWhenWindowHasFocus { innerJob = launch { awaitCancellation() } }
+ }
+ runCurrent()
+
+ assertThat(innerJob?.isActive).isEqualTo(true)
+ }
+
+ @Test
+ fun repeatWhenWindowHasFocus_startsWithoutFocus_runsBlockWhenFocused() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(true)
+ whenever(view.windowVisibility).thenReturn(View.VISIBLE)
+ whenever(view.hasWindowFocus()).thenReturn(false)
+
+ var innerJob: Job? = null
+ backgroundScope.launch {
+ view.repeatWhenWindowHasFocus { innerJob = launch { awaitCancellation() } }
+ }
+ runCurrent()
+
+ assertThat(innerJob?.isActive).isNotEqualTo(true)
+
+ whenever(view.hasWindowFocus()).thenReturn(true)
+
+ argCaptor { verify(viewTreeObserver).addOnWindowFocusChangeListener(capture()) }
+ .forEach { it.onWindowFocusChanged(true) }
+ runCurrent()
+
+ assertThat(innerJob?.isActive).isEqualTo(true)
+ }
+
+ @Test
+ fun repeatWhenWindowHasFocus_losesFocus_cancelsBlock() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(true)
+ whenever(view.windowVisibility).thenReturn(View.VISIBLE)
+ whenever(view.hasWindowFocus()).thenReturn(true)
+
+ var innerJob: Job? = null
+ backgroundScope.launch {
+ view.repeatWhenWindowHasFocus { innerJob = launch { awaitCancellation() } }
+ }
+ runCurrent()
+
+ assertThat(innerJob?.isActive).isEqualTo(true)
+
+ whenever(view.hasWindowFocus()).thenReturn(false)
+ argCaptor { verify(viewTreeObserver).addOnWindowFocusChangeListener(capture()) }
+ .forEach { it.onWindowFocusChanged(false) }
+ runCurrent()
+
+ assertThat(innerJob?.isActive).isNotEqualTo(true)
+ }
+
+ @Test
fun repeatWhenAttached_becomesVisibleWithoutFocus_STARTED() =
testScope.runTest {
whenever(view.isAttachedToWindow).thenReturn(true)
@@ -180,7 +366,7 @@
verify(viewTreeObserver).addOnWindowVisibilityChangeListener(listenerCaptor.capture())
whenever(view.windowVisibility).thenReturn(View.VISIBLE)
- listenerCaptor.value.onWindowVisibilityChanged(View.VISIBLE)
+ listenerCaptor.lastValue.onWindowVisibilityChanged(View.VISIBLE)
runCurrent()
assertThat(block.invocationCount).isEqualTo(1)
@@ -196,7 +382,7 @@
verify(viewTreeObserver).addOnWindowFocusChangeListener(listenerCaptor.capture())
whenever(view.hasWindowFocus()).thenReturn(true)
- listenerCaptor.value.onWindowFocusChanged(true)
+ listenerCaptor.lastValue.onWindowFocusChanged(true)
runCurrent()
assertThat(block.invocationCount).isEqualTo(1)
@@ -214,9 +400,9 @@
verify(viewTreeObserver).addOnWindowFocusChangeListener(focusCaptor.capture())
whenever(view.windowVisibility).thenReturn(View.VISIBLE)
- visibleCaptor.value.onWindowVisibilityChanged(View.VISIBLE)
+ visibleCaptor.lastValue.onWindowVisibilityChanged(View.VISIBLE)
whenever(view.hasWindowFocus()).thenReturn(true)
- focusCaptor.value.onWindowFocusChanged(true)
+ focusCaptor.lastValue.onWindowFocusChanged(true)
runCurrent()
assertThat(block.invocationCount).isEqualTo(1)
@@ -314,6 +500,7 @@
val invocations: List<Invocation> = _invocations
val invocationCount: Int
get() = _invocations.size
+
val latestLifecycleState: Lifecycle.State
get() = _invocations.last().lifecycleState
@@ -322,3 +509,9 @@
}
}
}
+
+private inline fun <reified T : Any> argCaptor(block: KArgumentCaptor<T>.() -> Unit) =
+ argumentCaptor<T>().apply { block() }
+
+private inline fun <reified T : Any> KArgumentCaptor<T>.forEach(block: (T) -> Unit): Unit =
+ allValues.forEach(block)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/ShareToAppPermissionDialogDelegateTest.kt
similarity index 81%
rename from packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegateTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/ShareToAppPermissionDialogDelegateTest.kt
index f884b87..c57aa36 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/ShareToAppPermissionDialogDelegateTest.kt
@@ -29,16 +29,16 @@
import com.android.systemui.res.R
import com.android.systemui.statusbar.phone.AlertDialogWithDelegate
import com.android.systemui.statusbar.phone.SystemUIDialog
-import com.android.systemui.util.mockito.mock
-import junit.framework.Assert.assertEquals
+import kotlin.test.assertEquals
import org.junit.After
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.kotlin.mock
@SmallTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
-class MediaProjectionPermissionDialogDelegateTest : SysuiTestCase() {
+class ShareToAppPermissionDialogDelegateTest : SysuiTestCase() {
private lateinit var dialog: AlertDialog
@@ -115,39 +115,16 @@
assertEquals(context.getString(resIdFullScreen), secondOptionText)
}
- @Test
- fun showDialog_disableSingleApp_hasCastingCapabilities() {
- setUpAndShowDialog(
- mediaProjectionConfig = MediaProjectionConfig.createConfigForDefaultDisplay(),
- hasCastingCapabilities = true
- )
-
- val spinner = dialog.requireViewById<Spinner>(R.id.screen_share_mode_options)
- val secondOptionWarningText =
- spinner.adapter
- .getDropDownView(1, null, spinner)
- .findViewById<TextView>(android.R.id.text2)
- ?.text
-
- // check that the first option is full screen and enabled
- assertEquals(context.getString(resIdFullScreen), spinner.selectedItem)
-
- // check that the second option is single app and disabled
- assertEquals(context.getString(resIdSingleAppDisabled, appName), secondOptionWarningText)
- }
-
private fun setUpAndShowDialog(
mediaProjectionConfig: MediaProjectionConfig? = null,
overrideDisableSingleAppOption: Boolean = false,
- hasCastingCapabilities: Boolean = false,
) {
val delegate =
- MediaProjectionPermissionDialogDelegate(
+ ShareToAppPermissionDialogDelegate(
context,
mediaProjectionConfig,
onStartRecordingClicked = {},
onCancelClicked = {},
- hasCastingCapabilities,
appName,
overrideDisableSingleAppOption,
hostUid = 12345,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/SystemCastPermissionDialogDelegateTest.kt
similarity index 77%
copy from packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegateTest.kt
copy to packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/SystemCastPermissionDialogDelegateTest.kt
index f884b87..59602dc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/SystemCastPermissionDialogDelegateTest.kt
@@ -29,23 +29,25 @@
import com.android.systemui.res.R
import com.android.systemui.statusbar.phone.AlertDialogWithDelegate
import com.android.systemui.statusbar.phone.SystemUIDialog
-import com.android.systemui.util.mockito.mock
-import junit.framework.Assert.assertEquals
+import kotlin.test.assertEquals
import org.junit.After
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.kotlin.mock
@SmallTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
-class MediaProjectionPermissionDialogDelegateTest : SysuiTestCase() {
+class SystemCastPermissionDialogDelegateTest : SysuiTestCase() {
private lateinit var dialog: AlertDialog
private val appName = "Test App"
- private val resIdSingleApp = R.string.screen_share_permission_dialog_option_single_app
- private val resIdFullScreen = R.string.screen_share_permission_dialog_option_entire_screen
+ private val resIdSingleApp =
+ R.string.media_projection_entry_cast_permission_dialog_option_text_single_app
+ private val resIdFullScreen =
+ R.string.media_projection_entry_cast_permission_dialog_option_text_entire_screen
private val resIdSingleAppDisabled =
R.string.media_projection_entry_app_permission_dialog_single_app_disabled
@@ -98,7 +100,7 @@
fun showDialog_disableSingleApp_forceShowPartialScreenShareTrue() {
setUpAndShowDialog(
mediaProjectionConfig = MediaProjectionConfig.createConfigForDefaultDisplay(),
- overrideDisableSingleAppOption = true
+ overrideDisableSingleAppOption = true,
)
val spinner = dialog.requireViewById<Spinner>(R.id.screen_share_mode_options)
@@ -115,43 +117,20 @@
assertEquals(context.getString(resIdFullScreen), secondOptionText)
}
- @Test
- fun showDialog_disableSingleApp_hasCastingCapabilities() {
- setUpAndShowDialog(
- mediaProjectionConfig = MediaProjectionConfig.createConfigForDefaultDisplay(),
- hasCastingCapabilities = true
- )
-
- val spinner = dialog.requireViewById<Spinner>(R.id.screen_share_mode_options)
- val secondOptionWarningText =
- spinner.adapter
- .getDropDownView(1, null, spinner)
- .findViewById<TextView>(android.R.id.text2)
- ?.text
-
- // check that the first option is full screen and enabled
- assertEquals(context.getString(resIdFullScreen), spinner.selectedItem)
-
- // check that the second option is single app and disabled
- assertEquals(context.getString(resIdSingleAppDisabled, appName), secondOptionWarningText)
- }
-
private fun setUpAndShowDialog(
mediaProjectionConfig: MediaProjectionConfig? = null,
overrideDisableSingleAppOption: Boolean = false,
- hasCastingCapabilities: Boolean = false,
) {
val delegate =
- MediaProjectionPermissionDialogDelegate(
+ SystemCastPermissionDialogDelegate(
context,
mediaProjectionConfig,
onStartRecordingClicked = {},
onCancelClicked = {},
- hasCastingCapabilities,
appName,
overrideDisableSingleAppOption,
hostUid = 12345,
- mediaProjectionMetricsLogger = mock<MediaProjectionMetricsLogger>()
+ mediaProjectionMetricsLogger = mock<MediaProjectionMetricsLogger>(),
)
dialog = AlertDialogWithDelegate(context, R.style.Theme_SystemUI_Dialog, delegate)
@@ -159,7 +138,7 @@
SystemUIDialog.setDialogSize(dialog)
dialog.window?.addSystemFlags(
- WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS
+ WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
)
delegate.onCreate(dialog, savedInstanceState = null)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/views/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/views/NavigationBarTest.java
index 45d77f6..a8cbbd4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/views/NavigationBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/views/NavigationBarTest.java
@@ -498,7 +498,7 @@
defaultNavBar.init();
externalNavBar.init();
- defaultNavBar.setImeWindowStatus(DEFAULT_DISPLAY, null, IME_VISIBLE,
+ defaultNavBar.setImeWindowStatus(DEFAULT_DISPLAY, IME_VISIBLE,
BACK_DISPOSITION_DEFAULT, true);
// Verify IME window state will be updated in default NavBar & external NavBar state reset.
@@ -510,10 +510,10 @@
assertFalse((externalNavBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SWITCHER_SHOWN)
!= 0);
- externalNavBar.setImeWindowStatus(EXTERNAL_DISPLAY_ID, null, IME_VISIBLE,
+ externalNavBar.setImeWindowStatus(EXTERNAL_DISPLAY_ID, IME_VISIBLE,
BACK_DISPOSITION_DEFAULT, true);
- defaultNavBar.setImeWindowStatus(
- DEFAULT_DISPLAY, null, IME_INVISIBLE, BACK_DISPOSITION_DEFAULT, false);
+ defaultNavBar.setImeWindowStatus(DEFAULT_DISPLAY, IME_INVISIBLE,
+ BACK_DISPOSITION_DEFAULT, false);
// Verify IME window state will be updated in external NavBar & default NavBar state reset.
assertEquals(NAVIGATION_HINT_BACK_ALT | NAVIGATION_HINT_IME_SHOWN
| NAVIGATION_HINT_IME_SWITCHER_SHOWN,
@@ -535,7 +535,7 @@
doReturn(windowInsets).when(mockShadeWindowView).getRootWindowInsets();
// Verify navbar altered back icon when an app is showing IME
- mNavigationBar.setImeWindowStatus(DEFAULT_DISPLAY, null, IME_VISIBLE,
+ mNavigationBar.setImeWindowStatus(DEFAULT_DISPLAY, IME_VISIBLE,
BACK_DISPOSITION_DEFAULT, true);
assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SHOWN) != 0);
@@ -545,7 +545,7 @@
// Verify navbar didn't alter and showing back icon when the keyguard is showing without
// requesting IME insets visible.
doReturn(true).when(mKeyguardStateController).isShowing();
- mNavigationBar.setImeWindowStatus(DEFAULT_DISPLAY, null, IME_VISIBLE,
+ mNavigationBar.setImeWindowStatus(DEFAULT_DISPLAY, IME_VISIBLE,
BACK_DISPOSITION_DEFAULT, true);
assertFalse((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
assertFalse((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SHOWN) != 0);
@@ -556,7 +556,7 @@
// requesting IME insets visible.
windowInsets = new WindowInsets.Builder().setVisible(ime(), true).build();
doReturn(windowInsets).when(mockShadeWindowView).getRootWindowInsets();
- mNavigationBar.setImeWindowStatus(DEFAULT_DISPLAY, null, IME_VISIBLE,
+ mNavigationBar.setImeWindowStatus(DEFAULT_DISPLAY, IME_VISIBLE,
BACK_DISPOSITION_DEFAULT, true);
assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SHOWN) != 0);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
index 0196f95..80a9e4c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
@@ -62,9 +62,8 @@
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.mockito.withArgCaptor
-import com.android.systemui.util.settings.SecureSettings
+import com.android.systemui.util.settings.FakeSettings
import com.android.wm.shell.bubbles.Bubble
import com.android.wm.shell.bubbles.Bubbles
import com.google.common.truth.Truth.assertThat
@@ -86,6 +85,7 @@
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyZeroInteractions
import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.whenever
/** atest SystemUITests:NoteTaskControllerTest */
@OptIn(ExperimentalCoroutinesApi::class)
@@ -106,10 +106,10 @@
@Mock private lateinit var shortcutManager: ShortcutManager
@Mock private lateinit var activityManager: ActivityManager
@Mock private lateinit var devicePolicyManager: DevicePolicyManager
- @Mock private lateinit var secureSettings: SecureSettings
private val userTracker = FakeUserTracker()
private val testDispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(testDispatcher)
+ private val secureSettings = FakeSettings(testDispatcher) { userTracker.userId }
@Before
fun setUp() {
@@ -139,7 +139,6 @@
whenever(activityManager.getRunningTasks(anyInt())).thenReturn(emptyList())
whenever(userManager.isManagedProfile(workUserInfo.id)).thenReturn(true)
whenever(context.resources).thenReturn(getContext().resources)
- whenever(secureSettings.userTracker).thenReturn(userTracker)
}
private fun createNoteTaskController(
@@ -245,6 +244,7 @@
verifyZeroInteractions(bubbles, keyguardManager, userManager, eventLogger)
}
+
// endregion
// region showNoteTask
@@ -357,14 +357,11 @@
@Test
fun showNoteTask_defaultUserSet_shouldStartActivityWithExpectedUserAndLogUiEvent() {
- whenever(
- secureSettings.getIntForUser(
- /* name= */ eq(Settings.Secure.DEFAULT_NOTE_TASK_PROFILE),
- /* def= */ any(),
- /* userHandle= */ any()
- )
- )
- .thenReturn(10)
+ secureSettings.putIntForUser(
+ /* name= */ Settings.Secure.DEFAULT_NOTE_TASK_PROFILE,
+ /* value= */ 10,
+ /* userHandle= */ userTracker.userId
+ )
val user10 = UserHandle.of(/* userId= */ 10)
val expectedInfo =
@@ -458,6 +455,7 @@
verify(eventLogger).logNoteTaskOpened(expectedInfo)
verifyZeroInteractions(bubbles)
}
+
// endregion
// region setNoteTaskShortcutEnabled
@@ -535,6 +533,7 @@
assertThat(argument.value.className)
.isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
}
+
// endregion
// region keyguard policy
@@ -601,6 +600,7 @@
verifyNoteTaskOpenInBubbleInUser(userTracker.userHandle)
}
+
// endregion
// region showNoteTask, COPE devices
@@ -626,14 +626,11 @@
@Test
fun showNoteTask_copeDevices_tailButtonEntryPoint_shouldStartBubbleInTheUserSelectedUser() {
- whenever(
- secureSettings.getIntForUser(
- /* name= */ eq(Settings.Secure.DEFAULT_NOTE_TASK_PROFILE),
- /* def= */ any(),
- /* userHandle= */ any()
- )
- )
- .thenReturn(mainUserInfo.id)
+ secureSettings.putIntForUser(
+ /* name= */ Settings.Secure.DEFAULT_NOTE_TASK_PROFILE,
+ /* value= */ mainUserInfo.id,
+ /* userHandle= */ userTracker.userId
+ )
whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
@@ -661,6 +658,7 @@
verifyNoteTaskOpenInBubbleInUser(mainUserInfo.userHandle)
}
+
// endregion
private fun verifyNoteTaskOpenInBubbleInUser(userHandle: UserHandle) {
@@ -700,6 +698,7 @@
verify(controller).updateNoteTaskAsUser(user)
}
+
// endregion
// region updateNoteTaskAsUser
@@ -729,6 +728,7 @@
val intent = withArgCaptor { verify(context).startServiceAsUser(capture(), eq(user)) }
assertThat(intent).hasComponentClass(NoteTaskControllerUpdateService::class.java)
}
+
// endregion
// region internalUpdateNoteTaskAsUser
@@ -807,6 +807,7 @@
verify(shortcutManager, never()).enableShortcuts(any())
verify(shortcutManager, never()).updateShortcuts(any())
}
+
// endregion
// startregion updateNoteTaskForAllUsers
@@ -821,6 +822,7 @@
verify(controller).updateNoteTaskAsUser(mainUserInfo.userHandle)
verify(controller).updateNoteTaskAsUser(workUserInfo.userHandle)
}
+
// endregion
// region getUserForHandlingNotesTaking
@@ -836,14 +838,11 @@
@Test
fun getUserForHandlingNotesTaking_cope_userSelectedWorkProfile_tailButton_shouldReturnWorkProfileUser() { // ktlint-disable max-line-length
- whenever(
- secureSettings.getIntForUser(
- /* name= */ eq(Settings.Secure.DEFAULT_NOTE_TASK_PROFILE),
- /* def= */ any(),
- /* userHandle= */ any()
- )
- )
- .thenReturn(workUserInfo.id)
+ secureSettings.putIntForUser(
+ /* name= */ Settings.Secure.DEFAULT_NOTE_TASK_PROFILE,
+ /* value= */ workUserInfo.id,
+ /* userHandle= */ userTracker.userId
+ )
whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
@@ -854,14 +853,11 @@
@Test
fun getUserForHandlingNotesTaking_cope_userSelectedMainProfile_tailButton_shouldReturnMainProfileUser() { // ktlint-disable max-line-length
- whenever(
- secureSettings.getIntForUser(
- /* name= */ eq(Settings.Secure.DEFAULT_NOTE_TASK_PROFILE),
- /* def= */ any(),
- /* userHandle= */ any()
- )
- )
- .thenReturn(mainUserInfo.id)
+ secureSettings.putIntForUser(
+ /* name= */ Settings.Secure.DEFAULT_NOTE_TASK_PROFILE,
+ /* value= */ mainUserInfo.id,
+ /* userHandle= */ userTracker.userId
+ )
whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
@@ -906,6 +902,7 @@
assertThat(user).isEqualTo(UserHandle.of(mainUserInfo.id))
}
+
// endregion
// startregion startNotesRoleSetting
@@ -962,6 +959,7 @@
assertThat(intentCaptor.value).hasAction(ACTION_MANAGE_DEFAULT_APP)
assertThat(userCaptor.value).isEqualTo(UserHandle.of(mainUserInfo.id))
}
+
// endregion
private companion object {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
index 4f4f0d9..2f41ac17 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
@@ -45,6 +45,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.app.viewcapture.ViewCapture;
import com.android.settingslib.fuelgauge.Estimate;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -54,6 +55,8 @@
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.CommandQueue;
+import dagger.Lazy;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -94,6 +97,7 @@
@Mock private BroadcastDispatcher mBroadcastDispatcher;
@Mock private CommandQueue mCommandQueue;
@Mock private IVrManager mVrManager;
+ @Mock private Lazy<ViewCapture> mLazyViewCapture;
@Before
public void setup() {
@@ -705,7 +709,8 @@
mEnhancedEstimates,
mWakefulnessLifecycle,
mPowerManager,
- mUserTracker);
+ mUserTracker,
+ mLazyViewCapture);
mPowerUI.mThermalService = mThermalServiceMock;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java
index c0d390a..206bbbf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java
@@ -554,6 +554,30 @@
assertThat(mUnderTest.isKeyguardState()).isFalse();
}
+ @Test
+ public void testHeaderBounds() {
+ int left = 20;
+ int top = 30;
+ int right = 200;
+ int bottom = 100;
+ setHeaderBounds(left, top, right, bottom);
+
+ assertThat(mUnderTest.getHeaderLeft()).isEqualTo(left);
+ assertThat(mUnderTest.getHeaderTop()).isEqualTo(top);
+ assertThat(mUnderTest.getHeaderBottom()).isEqualTo(bottom);
+ assertThat(mUnderTest.getHeaderHeight()).isEqualTo(bottom - top);
+ }
+
+ @Test
+ public void testHeaderBoundsOnScreen() {
+ Rect bounds = new Rect(0, 10, 100, 200);
+ setHeaderBoundsOnScreen(bounds);
+
+ Rect out = new Rect();
+ mUnderTest.getHeaderBoundsOnScreen(out);
+ assertThat(out).isEqualTo(bounds);
+ }
+
private QSImpl instantiate() {
setupQsComponent();
setUpViews();
@@ -672,4 +696,19 @@
private void setIsSmallScreen() {
mUnderTest.setIsNotificationPanelFullWidth(true);
}
+
+ private void setHeaderBounds(int left, int top, int right, int bottom) {
+ when(mHeader.getLeft()).thenReturn(left);
+ when(mHeader.getTop()).thenReturn(top);
+ when(mHeader.getRight()).thenReturn(right);
+ when(mHeader.getBottom()).thenReturn(bottom);
+ }
+
+ private void setHeaderBoundsOnScreen(Rect rect) {
+ doAnswer(invocation -> {
+ Rect bounds = invocation.getArgument(/* index= */ 0);
+ bounds.set(rect);
+ return null;
+ }).when(mHeader).getBoundsOnScreen(any(Rect.class));
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
index e1c3911..b02cccc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
@@ -35,6 +35,7 @@
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
+import com.android.systemui.education.domain.interactor.KeyboardTouchpadEduStatsInteractor
import com.android.systemui.keyguard.KeyguardUnlockAnimationController
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.ui.view.InWindowLauncherUnlockAnimationManager
@@ -121,6 +122,9 @@
Optional<UnfoldTransitionProgressForwarder>
@Mock private lateinit var broadcastDispatcher: BroadcastDispatcher
+ @Mock
+ private lateinit var keyboardTouchpadEduStatsInteractor: KeyboardTouchpadEduStatsInteractor
+
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
@@ -289,7 +293,8 @@
assistUtils,
dumpManager,
unfoldTransitionProgressForwarder,
- broadcastDispatcher
+ broadcastDispatcher,
+ keyboardTouchpadEduStatsInteractor
)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
index 56fb43d..2803035 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -479,7 +479,6 @@
mKeyguardLogger,
mKosmos.getInteractionJankMonitor(),
mKeyguardInteractor,
- mDumpManager,
mPowerInteractor));
when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
index b7ce336..e57382d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
@@ -252,6 +252,8 @@
when(mQsFrame.getWidth()).thenReturn(QS_FRAME_WIDTH);
when(mQsHeader.getTop()).thenReturn(QS_FRAME_TOP);
when(mQsHeader.getBottom()).thenReturn(QS_FRAME_BOTTOM);
+ when(mQs.getHeaderTop()).thenReturn(QS_FRAME_TOP);
+ when(mQs.getHeaderBottom()).thenReturn(QS_FRAME_BOTTOM);
when(mPanelView.getY()).thenReturn((float) QS_FRAME_TOP);
when(mPanelView.getHeight()).thenReturn(QS_FRAME_BOTTOM);
when(mPanelView.findViewById(R.id.keyguard_status_view))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplTest.java
index 7ab3e29..e7db469 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.shade;
+import static android.platform.test.flag.junit.FlagsParameterization.progressionOf;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_POINTER_DOWN;
@@ -23,6 +24,8 @@
import static android.view.MotionEvent.BUTTON_SECONDARY;
import static android.view.MotionEvent.BUTTON_STYLUS_PRIMARY;
+import static com.android.systemui.Flags.FLAG_QS_UI_REFACTOR;
+import static com.android.systemui.Flags.FLAG_QS_UI_REFACTOR_COMPOSE_FRAGMENT;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.StatusBarState.SHADE;
@@ -36,10 +39,10 @@
import static org.mockito.Mockito.when;
import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.FlagsParameterization;
import android.testing.TestableLooper;
import android.view.MotionEvent;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.systemui.plugins.qs.QS;
@@ -52,11 +55,24 @@
import java.util.List;
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
@SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(ParameterizedAndroidJunit4.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class QuickSettingsControllerImplTest extends QuickSettingsControllerImplBaseTest {
+ @Parameters(name = "{0}")
+ public static List<FlagsParameterization> getParams() {
+ return progressionOf(FLAG_QS_UI_REFACTOR, FLAG_QS_UI_REFACTOR_COMPOSE_FRAGMENT);
+ }
+
+ public QuickSettingsControllerImplTest(FlagsParameterization flags) {
+ super();
+ mSetFlagsRule.setFlagsParameterization(flags);
+ }
+
@Test
public void testCloseQsSideEffects() {
enableSplitShade(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryTest.kt
index 30326a57..35f2e6e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.shared.notifications.data.repository
import android.provider.Settings
+import android.provider.Settings.Secure.ZEN_DURATION_FOREVER
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
@@ -50,7 +51,7 @@
underTest =
NotificationSettingsRepository(
- scope = testScope.backgroundScope,
+ backgroundScope = testScope.backgroundScope,
backgroundDispatcher = testDispatcher,
secureSettingsRepository = secureSettingsRepository,
systemSettingsRepository = systemSettingsRepository,
@@ -58,7 +59,7 @@
}
@Test
- fun testGetIsShowNotificationsOnLockscreenEnabled() =
+ fun getIsShowNotificationsOnLockscreenEnabled() =
testScope.runTest {
val showNotifs by collectLastValue(underTest.isShowNotificationsOnLockScreenEnabled())
@@ -76,7 +77,7 @@
}
@Test
- fun testSetIsShowNotificationsOnLockscreenEnabled() =
+ fun setIsShowNotificationsOnLockscreenEnabled() =
testScope.runTest {
val showNotifs by collectLastValue(underTest.isShowNotificationsOnLockScreenEnabled())
@@ -88,7 +89,7 @@
}
@Test
- fun testGetIsNotificationHistoryEnabled() =
+ fun getIsNotificationHistoryEnabled() =
testScope.runTest {
val historyEnabled by collectLastValue(underTest.isNotificationHistoryEnabled)
@@ -122,4 +123,22 @@
)
assertThat(cooldownEnabled).isEqualTo(false)
}
+
+ @Test
+ fun zenDuration() =
+ testScope.runTest {
+ val zenDuration by collectLastValue(underTest.zenDuration)
+
+ secureSettingsRepository.setInt(
+ name = Settings.Secure.ZEN_DURATION,
+ value = 60,
+ )
+ assertThat(zenDuration).isEqualTo(60)
+
+ secureSettingsRepository.setInt(
+ name = Settings.Secure.ZEN_DURATION,
+ value = ZEN_DURATION_FOREVER,
+ )
+ assertThat(zenDuration).isEqualTo(ZEN_DURATION_FOREVER)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
index 9df46e5..86d21e8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -195,10 +195,9 @@
@Test
public void testShowImeButton() {
- mCommandQueue.setImeWindowStatus(DEFAULT_DISPLAY, null, 1, 2, true);
+ mCommandQueue.setImeWindowStatus(DEFAULT_DISPLAY, 1, 2, true);
waitForIdleSync();
- verify(mCallbacks).setImeWindowStatus(
- eq(DEFAULT_DISPLAY), eq(null), eq(1), eq(2), eq(true));
+ verify(mCallbacks).setImeWindowStatus(eq(DEFAULT_DISPLAY), eq(1), eq(2), eq(true));
}
@Test
@@ -206,12 +205,11 @@
// First show in default display to update the "last updated ime display"
testShowImeButton();
- mCommandQueue.setImeWindowStatus(SECONDARY_DISPLAY, null, 1, 2, true);
+ mCommandQueue.setImeWindowStatus(SECONDARY_DISPLAY, 1, 2, true);
waitForIdleSync();
- verify(mCallbacks).setImeWindowStatus(eq(DEFAULT_DISPLAY), eq(null), eq(IME_INVISIBLE),
+ verify(mCallbacks).setImeWindowStatus(eq(DEFAULT_DISPLAY), eq(IME_INVISIBLE),
eq(BACK_DISPOSITION_DEFAULT), eq(false));
- verify(mCallbacks).setImeWindowStatus(
- eq(SECONDARY_DISPLAY), eq(null), eq(1), eq(2), eq(true));
+ verify(mCallbacks).setImeWindowStatus(eq(SECONDARY_DISPLAY), eq(1), eq(2), eq(true));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/statusbar/OWNERS
new file mode 100644
index 0000000..1c52b8d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/OWNERS
@@ -0,0 +1,3 @@
+set noparent
+
+include /packages/SystemUI/src/com/android/systemui/statusbar/OWNERS
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/call/domain/interactor/CallChipInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/call/domain/interactor/CallChipInteractorTest.kt
index cd8a740..8f41caf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/call/domain/interactor/CallChipInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/call/domain/interactor/CallChipInteractorTest.kt
@@ -23,6 +23,7 @@
import com.android.systemui.kosmos.testScope
import com.android.systemui.statusbar.phone.ongoingcall.data.repository.ongoingCallRepository
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel
+import com.android.systemui.statusbar.phone.ongoingcall.shared.model.inCallModel
import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
import kotlinx.coroutines.test.runTest
@@ -39,7 +40,7 @@
kosmos.testScope.runTest {
val latest by collectLastValue(underTest.ongoingCallState)
- val inCall = OngoingCallModel.InCall(startTimeMs = 1000, intent = null)
+ val inCall = inCallModel(startTimeMs = 1000)
repo.setOngoingCallState(inCall)
assertThat(latest).isEqualTo(inCall)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
index 1a6b420..ce79fbd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
@@ -17,8 +17,11 @@
package com.android.systemui.statusbar.chips.call.ui.viewmodel
import android.app.PendingIntent
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
import android.view.View
import androidx.test.filters.SmallTest
+import com.android.systemui.Flags.FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.coroutines.collectLastValue
@@ -26,11 +29,13 @@
import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.activityStarter
import com.android.systemui.res.R
+import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.phone.ongoingcall.data.repository.ongoingCallRepository
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel
+import com.android.systemui.statusbar.phone.ongoingcall.shared.model.inCallModel
import com.android.systemui.util.time.fakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
@@ -73,7 +78,7 @@
testScope.runTest {
val latest by collectLastValue(underTest.chip)
- repo.setOngoingCallState(OngoingCallModel.InCall(startTimeMs = 0, intent = null))
+ repo.setOngoingCallState(inCallModel(startTimeMs = 0))
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown.IconOnly::class.java)
}
@@ -83,7 +88,7 @@
testScope.runTest {
val latest by collectLastValue(underTest.chip)
- repo.setOngoingCallState(OngoingCallModel.InCall(startTimeMs = -2, intent = null))
+ repo.setOngoingCallState(inCallModel(startTimeMs = -2))
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown.IconOnly::class.java)
}
@@ -93,7 +98,7 @@
testScope.runTest {
val latest by collectLastValue(underTest.chip)
- repo.setOngoingCallState(OngoingCallModel.InCall(startTimeMs = 345, intent = null))
+ repo.setOngoingCallState(inCallModel(startTimeMs = 345))
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown.Timer::class.java)
}
@@ -106,7 +111,7 @@
kosmos.fakeSystemClock.setCurrentTimeMillis(3000)
kosmos.fakeSystemClock.setElapsedRealtime(400_000)
- repo.setOngoingCallState(OngoingCallModel.InCall(startTimeMs = 1000, intent = null))
+ repo.setOngoingCallState(inCallModel(startTimeMs = 1000))
// The OngoingCallModel start time is relative to currentTimeMillis, so this call
// started 2000ms ago (1000 - 3000). The OngoingActivityChipModel start time needs to be
@@ -117,29 +122,97 @@
}
@Test
- fun chip_positiveStartTime_iconIsPhone() =
+ @DisableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON)
+ fun chip_positiveStartTime_notifIconFlagOff_iconIsPhone() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
- repo.setOngoingCallState(OngoingCallModel.InCall(startTimeMs = 1000, intent = null))
+ repo.setOngoingCallState(
+ inCallModel(startTimeMs = 1000, notificationIcon = mock<StatusBarIconView>())
+ )
- assertThat(((latest as OngoingActivityChipModel.Shown).icon as Icon.Resource).res)
- .isEqualTo(com.android.internal.R.drawable.ic_phone)
- assertThat((latest as OngoingActivityChipModel.Shown).icon!!.contentDescription)
- .isNotNull()
+ assertThat((latest as OngoingActivityChipModel.Shown).icon)
+ .isInstanceOf(OngoingActivityChipModel.ChipIcon.Basic::class.java)
+ val icon =
+ (((latest as OngoingActivityChipModel.Shown).icon)
+ as OngoingActivityChipModel.ChipIcon.Basic)
+ .impl as Icon.Resource
+ assertThat(icon.res).isEqualTo(com.android.internal.R.drawable.ic_phone)
+ assertThat(icon.contentDescription).isNotNull()
}
@Test
- fun chip_zeroStartTime_iconIsPhone() =
+ @EnableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON)
+ fun chip_positiveStartTime_notifIconFlagOn_iconIsNotifIcon() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
- repo.setOngoingCallState(OngoingCallModel.InCall(startTimeMs = 0, intent = null))
+ val notifIcon = mock<StatusBarIconView>()
+ repo.setOngoingCallState(inCallModel(startTimeMs = 1000, notificationIcon = notifIcon))
- assertThat(((latest as OngoingActivityChipModel.Shown).icon as Icon.Resource).res)
- .isEqualTo(com.android.internal.R.drawable.ic_phone)
- assertThat((latest as OngoingActivityChipModel.Shown).icon!!.contentDescription)
- .isNotNull()
+ assertThat((latest as OngoingActivityChipModel.Shown).icon)
+ .isInstanceOf(OngoingActivityChipModel.ChipIcon.StatusBarView::class.java)
+ val actualIcon =
+ (((latest as OngoingActivityChipModel.Shown).icon)
+ as OngoingActivityChipModel.ChipIcon.StatusBarView)
+ .impl
+ assertThat(actualIcon).isEqualTo(notifIcon)
+ }
+
+ @Test
+ @DisableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON)
+ fun chip_zeroStartTime_notifIconFlagOff_iconIsPhone() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+
+ repo.setOngoingCallState(
+ inCallModel(startTimeMs = 0, notificationIcon = mock<StatusBarIconView>())
+ )
+
+ assertThat((latest as OngoingActivityChipModel.Shown).icon)
+ .isInstanceOf(OngoingActivityChipModel.ChipIcon.Basic::class.java)
+ val icon =
+ (((latest as OngoingActivityChipModel.Shown).icon)
+ as OngoingActivityChipModel.ChipIcon.Basic)
+ .impl as Icon.Resource
+ assertThat(icon.res).isEqualTo(com.android.internal.R.drawable.ic_phone)
+ assertThat(icon.contentDescription).isNotNull()
+ }
+
+ @Test
+ @EnableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON)
+ fun chip_zeroStartTime_notifIconFlagOn_iconIsNotifIcon() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+
+ val notifIcon = mock<StatusBarIconView>()
+ repo.setOngoingCallState(inCallModel(startTimeMs = 0, notificationIcon = notifIcon))
+
+ assertThat((latest as OngoingActivityChipModel.Shown).icon)
+ .isInstanceOf(OngoingActivityChipModel.ChipIcon.StatusBarView::class.java)
+ val actualIcon =
+ (((latest as OngoingActivityChipModel.Shown).icon)
+ as OngoingActivityChipModel.ChipIcon.StatusBarView)
+ .impl
+ assertThat(actualIcon).isEqualTo(notifIcon)
+ }
+
+ @Test
+ @EnableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON)
+ fun chip_notifIconFlagOn_butNullNotifIcon_iconIsPhone() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+
+ repo.setOngoingCallState(inCallModel(startTimeMs = 1000, notificationIcon = null))
+
+ assertThat((latest as OngoingActivityChipModel.Shown).icon)
+ .isInstanceOf(OngoingActivityChipModel.ChipIcon.Basic::class.java)
+ val icon =
+ (((latest as OngoingActivityChipModel.Shown).icon)
+ as OngoingActivityChipModel.ChipIcon.Basic)
+ .impl as Icon.Resource
+ assertThat(icon.res).isEqualTo(com.android.internal.R.drawable.ic_phone)
+ assertThat(icon.contentDescription).isNotNull()
}
@Test
@@ -147,7 +220,7 @@
testScope.runTest {
val latest by collectLastValue(underTest.chip)
- repo.setOngoingCallState(OngoingCallModel.InCall(startTimeMs = 1000, intent = null))
+ repo.setOngoingCallState(inCallModel(startTimeMs = 1000))
assertThat((latest as OngoingActivityChipModel.Shown).colors)
.isEqualTo(ColorsModel.Themed)
@@ -158,7 +231,7 @@
testScope.runTest {
val latest by collectLastValue(underTest.chip)
- repo.setOngoingCallState(OngoingCallModel.InCall(startTimeMs = 0, intent = null))
+ repo.setOngoingCallState(inCallModel(startTimeMs = 0))
assertThat((latest as OngoingActivityChipModel.Shown).colors)
.isEqualTo(ColorsModel.Themed)
@@ -172,7 +245,7 @@
kosmos.fakeSystemClock.setElapsedRealtime(400_000)
// Start a call
- repo.setOngoingCallState(OngoingCallModel.InCall(startTimeMs = 1000, intent = null))
+ repo.setOngoingCallState(inCallModel(startTimeMs = 1000))
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown::class.java)
assertThat((latest as OngoingActivityChipModel.Shown.Timer).startTimeMs)
.isEqualTo(398_000)
@@ -186,7 +259,7 @@
kosmos.fakeSystemClock.setElapsedRealtime(500_000)
// Start a new call, which started 1000ms ago
- repo.setOngoingCallState(OngoingCallModel.InCall(startTimeMs = 102_000, intent = null))
+ repo.setOngoingCallState(inCallModel(startTimeMs = 102_000))
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown::class.java)
assertThat((latest as OngoingActivityChipModel.Shown.Timer).startTimeMs)
.isEqualTo(499_000)
@@ -197,7 +270,7 @@
testScope.runTest {
val latest by collectLastValue(underTest.chip)
- repo.setOngoingCallState(OngoingCallModel.InCall(startTimeMs = 1000, intent = null))
+ repo.setOngoingCallState(inCallModel(startTimeMs = 1000, intent = null))
assertThat((latest as OngoingActivityChipModel.Shown).onClickListener).isNull()
}
@@ -208,7 +281,7 @@
val latest by collectLastValue(underTest.chip)
val intent = mock<PendingIntent>()
- repo.setOngoingCallState(OngoingCallModel.InCall(startTimeMs = 1000, intent = intent))
+ repo.setOngoingCallState(inCallModel(startTimeMs = 1000, intent = intent))
val clickListener = (latest as OngoingActivityChipModel.Shown).onClickListener
assertThat(clickListener).isNotNull()
@@ -223,7 +296,7 @@
val latest by collectLastValue(underTest.chip)
val intent = mock<PendingIntent>()
- repo.setOngoingCallState(OngoingCallModel.InCall(startTimeMs = 0, intent = intent))
+ repo.setOngoingCallState(inCallModel(startTimeMs = 0, intent = intent))
val clickListener = (latest as OngoingActivityChipModel.Shown).onClickListener
assertThat(clickListener).isNotNull()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelTest.kt
index 02764f8..a8d2c5b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelTest.kt
@@ -125,8 +125,11 @@
)
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown.Timer::class.java)
- val icon = (latest as OngoingActivityChipModel.Shown).icon
- assertThat((icon as Icon.Resource).res).isEqualTo(R.drawable.ic_cast_connected)
+ val icon =
+ (((latest as OngoingActivityChipModel.Shown).icon)
+ as OngoingActivityChipModel.ChipIcon.Basic)
+ .impl as Icon.Resource
+ assertThat(icon.res).isEqualTo(R.drawable.ic_cast_connected)
assertThat((icon.contentDescription as ContentDescription.Resource).res)
.isEqualTo(R.string.cast_screen_to_other_device_chip_accessibility_label)
}
@@ -141,8 +144,11 @@
MediaProjectionState.Projecting.EntireScreen(CAST_TO_OTHER_DEVICES_PACKAGE)
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown.Timer::class.java)
- val icon = (latest as OngoingActivityChipModel.Shown).icon
- assertThat((icon as Icon.Resource).res).isEqualTo(R.drawable.ic_cast_connected)
+ val icon =
+ (((latest as OngoingActivityChipModel.Shown).icon)
+ as OngoingActivityChipModel.ChipIcon.Basic)
+ .impl as Icon.Resource
+ assertThat(icon.res).isEqualTo(R.drawable.ic_cast_connected)
assertThat((icon.contentDescription as ContentDescription.Resource).res)
.isEqualTo(R.string.cast_screen_to_other_device_chip_accessibility_label)
}
@@ -176,8 +182,11 @@
)
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown.IconOnly::class.java)
- val icon = (latest as OngoingActivityChipModel.Shown).icon
- assertThat((icon as Icon.Resource).res).isEqualTo(R.drawable.ic_cast_connected)
+ val icon =
+ (((latest as OngoingActivityChipModel.Shown).icon)
+ as OngoingActivityChipModel.ChipIcon.Basic)
+ .impl as Icon.Resource
+ assertThat(icon.res).isEqualTo(R.drawable.ic_cast_connected)
// This content description is just generic "Casting", not "Casting screen"
assertThat((icon.contentDescription as ContentDescription.Resource).res)
.isEqualTo(R.string.accessibility_casting)
@@ -203,8 +212,11 @@
// Only the projection info will show a timer
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown.Timer::class.java)
- val icon = (latest as OngoingActivityChipModel.Shown).icon
- assertThat((icon as Icon.Resource).res).isEqualTo(R.drawable.ic_cast_connected)
+ val icon =
+ (((latest as OngoingActivityChipModel.Shown).icon)
+ as OngoingActivityChipModel.ChipIcon.Basic)
+ .impl as Icon.Resource
+ assertThat(icon.res).isEqualTo(R.drawable.ic_cast_connected)
// MediaProjection == screen casting, so this content description reflects that we're
// using the MediaProjection information.
assertThat((icon.contentDescription as ContentDescription.Resource).res)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelTest.kt
index b4a37ee..e68fa0b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelTest.kt
@@ -148,8 +148,11 @@
screenRecordRepo.screenRecordState.value = ScreenRecordModel.Recording
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown.Timer::class.java)
- val icon = (latest as OngoingActivityChipModel.Shown).icon
- assertThat((icon as Icon.Resource).res).isEqualTo(R.drawable.ic_screenrecord)
+ val icon =
+ (((latest as OngoingActivityChipModel.Shown).icon)
+ as OngoingActivityChipModel.ChipIcon.Basic)
+ .impl as Icon.Resource
+ assertThat(icon.res).isEqualTo(R.drawable.ic_screenrecord)
assertThat(icon.contentDescription).isNotNull()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelTest.kt
index 2658679..a2ef599 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelTest.kt
@@ -133,8 +133,11 @@
)
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown.Timer::class.java)
- val icon = (latest as OngoingActivityChipModel.Shown).icon
- assertThat((icon as Icon.Resource).res).isEqualTo(R.drawable.ic_present_to_all)
+ val icon =
+ (((latest as OngoingActivityChipModel.Shown).icon)
+ as OngoingActivityChipModel.ChipIcon.Basic)
+ .impl as Icon.Resource
+ assertThat(icon.res).isEqualTo(R.drawable.ic_present_to_all)
assertThat(icon.contentDescription).isNotNull()
}
@@ -147,8 +150,11 @@
MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown.Timer::class.java)
- val icon = (latest as OngoingActivityChipModel.Shown).icon
- assertThat((icon as Icon.Resource).res).isEqualTo(R.drawable.ic_present_to_all)
+ val icon =
+ (((latest as OngoingActivityChipModel.Shown).icon)
+ as OngoingActivityChipModel.ChipIcon.Basic)
+ .impl as Icon.Resource
+ assertThat(icon.res).isEqualTo(R.drawable.ic_present_to_all)
assertThat(icon.contentDescription).isNotNull()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChipTransitionHelperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChipTransitionHelperTest.kt
index b9049e8..a724cfaa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChipTransitionHelperTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChipTransitionHelperTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.chips.ui.viewmodel
+import androidx.annotation.DrawableRes
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.Icon
@@ -50,7 +51,7 @@
val newChip =
OngoingActivityChipModel.Shown.Timer(
- icon = Icon.Resource(R.drawable.ic_cake, contentDescription = null),
+ icon = createIcon(R.drawable.ic_cake),
colors = ColorsModel.Themed,
startTimeMs = 100L,
onClickListener = null,
@@ -62,7 +63,7 @@
val newerChip =
OngoingActivityChipModel.Shown.IconOnly(
- icon = Icon.Resource(R.drawable.ic_hotspot, contentDescription = null),
+ icon = createIcon(R.drawable.ic_hotspot),
colors = ColorsModel.Themed,
onClickListener = null,
)
@@ -82,7 +83,7 @@
val shownChip =
OngoingActivityChipModel.Shown.Timer(
- icon = Icon.Resource(R.drawable.ic_cake, contentDescription = null),
+ icon = createIcon(R.drawable.ic_cake),
colors = ColorsModel.Themed,
startTimeMs = 100L,
onClickListener = null,
@@ -122,7 +123,7 @@
val shownChip =
OngoingActivityChipModel.Shown.Timer(
- icon = Icon.Resource(R.drawable.ic_cake, contentDescription = null),
+ icon = createIcon(R.drawable.ic_cake),
colors = ColorsModel.Themed,
startTimeMs = 100L,
onClickListener = null,
@@ -151,4 +152,7 @@
advanceTimeBy(2)
assertThat(latest).isEqualTo(shownChip)
}
+
+ private fun createIcon(@DrawableRes drawable: Int) =
+ OngoingActivityChipModel.ChipIcon.Basic(Icon.Resource(drawable, contentDescription = null))
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
index ee249f0..556ec6a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
@@ -42,6 +42,7 @@
import com.android.systemui.statusbar.phone.mockSystemUIDialogFactory
import com.android.systemui.statusbar.phone.ongoingcall.data.repository.ongoingCallRepository
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel
+import com.android.systemui.statusbar.phone.ongoingcall.shared.model.inCallModel
import com.android.systemui.util.time.fakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -120,7 +121,7 @@
testScope.runTest {
screenRecordState.value = ScreenRecordModel.Recording
- callRepo.setOngoingCallState(OngoingCallModel.InCall(startTimeMs = 34, intent = null))
+ callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
val latest by collectLastValue(underTest.chip)
@@ -146,7 +147,7 @@
screenRecordState.value = ScreenRecordModel.DoingNothing
mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)
- callRepo.setOngoingCallState(OngoingCallModel.InCall(startTimeMs = 34, intent = null))
+ callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
val latest by collectLastValue(underTest.chip)
@@ -160,7 +161,7 @@
// MediaProjection covers both share-to-app and cast-to-other-device
mediaProjectionState.value = MediaProjectionState.NotProjecting
- callRepo.setOngoingCallState(OngoingCallModel.InCall(startTimeMs = 34, intent = null))
+ callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
val latest by collectLastValue(underTest.chip)
@@ -171,7 +172,7 @@
fun chip_higherPriorityChipAdded_lowerPriorityChipReplaced() =
testScope.runTest {
// Start with just the lower priority call chip
- callRepo.setOngoingCallState(OngoingCallModel.InCall(startTimeMs = 34, intent = null))
+ callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
mediaProjectionState.value = MediaProjectionState.NotProjecting
screenRecordState.value = ScreenRecordModel.DoingNothing
@@ -205,7 +206,7 @@
mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)
- callRepo.setOngoingCallState(OngoingCallModel.InCall(startTimeMs = 34, intent = null))
+ callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
val latest by collectLastValue(underTest.chip)
@@ -335,21 +336,29 @@
fun assertIsScreenRecordChip(latest: OngoingActivityChipModel?) {
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown::class.java)
- val icon = (latest as OngoingActivityChipModel.Shown).icon
- assertThat((icon as Icon.Resource).res).isEqualTo(R.drawable.ic_screenrecord)
+ val icon =
+ (((latest as OngoingActivityChipModel.Shown).icon)
+ as OngoingActivityChipModel.ChipIcon.Basic)
+ .impl as Icon.Resource
+ assertThat(icon.res).isEqualTo(R.drawable.ic_screenrecord)
}
fun assertIsShareToAppChip(latest: OngoingActivityChipModel?) {
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown::class.java)
- val icon = (latest as OngoingActivityChipModel.Shown).icon
- assertThat((icon as Icon.Resource).res).isEqualTo(R.drawable.ic_present_to_all)
+ val icon =
+ (((latest as OngoingActivityChipModel.Shown).icon)
+ as OngoingActivityChipModel.ChipIcon.Basic)
+ .impl as Icon.Resource
+ assertThat(icon.res).isEqualTo(R.drawable.ic_present_to_all)
}
fun assertIsCallChip(latest: OngoingActivityChipModel?) {
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown::class.java)
- val icon = (latest as OngoingActivityChipModel.Shown).icon
- assertThat((icon as Icon.Resource).res)
- .isEqualTo(com.android.internal.R.drawable.ic_phone)
+ val icon =
+ (((latest as OngoingActivityChipModel.Shown).icon)
+ as OngoingActivityChipModel.ChipIcon.Basic)
+ .impl as Icon.Resource
+ assertThat(icon.res).isEqualTo(com.android.internal.R.drawable.ic_phone)
}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt
index 6a5976e..48ae7a2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt
@@ -39,6 +39,7 @@
import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent
import com.android.systemui.statusbar.phone.ongoingcall.data.repository.ongoingCallRepository
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel
+import com.android.systemui.statusbar.phone.ongoingcall.shared.model.inCallModel
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.capture
@@ -396,9 +397,7 @@
testScope.runTest {
val latest by collectLastValue(underTest.statusBarAppearance)
- ongoingCallRepository.setOngoingCallState(
- OngoingCallModel.InCall(startTimeMs = 34, intent = null)
- )
+ ongoingCallRepository.setOngoingCallState(inCallModel(startTimeMs = 34))
onSystemBarAttributesChanged(
requestedVisibleTypes = WindowInsets.Type.navigationBars(),
)
@@ -411,9 +410,8 @@
testScope.runTest {
val latest by collectLastValue(underTest.statusBarAppearance)
- ongoingCallRepository.setOngoingCallState(
- OngoingCallModel.InCall(startTimeMs = 789, intent = null)
- )
+ ongoingCallRepository.setOngoingCallState(inCallModel(startTimeMs = 789))
+
onSystemBarAttributesChanged(
requestedVisibleTypes = WindowInsets.Type.statusBars(),
appearance = APPEARANCE_OPAQUE_STATUS_BARS,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt
index 277b887..572a0c1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt
@@ -15,6 +15,8 @@
package com.android.systemui.statusbar.notification.domain.interactor
+import android.app.Notification
+import android.os.Bundle
import android.service.notification.StatusBarNotification
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -139,9 +141,10 @@
}
private fun mockNotificationEntry(key: String, rank: Int = 0): NotificationEntry {
+ val mockNotification = mock<Notification> { this.extras = Bundle() }
val mockSbn =
mock<StatusBarNotification>() {
- whenever(notification).thenReturn(mock())
+ whenever(notification).thenReturn(mockNotification)
whenever(packageName).thenReturn("com.android")
}
return mock<NotificationEntry> {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt
index bfa816e..25138fd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt
@@ -30,9 +30,12 @@
import android.os.Bundle
import android.os.SystemClock
import android.os.UserHandle
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
import androidx.test.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.systemui.Flags.FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON
import com.android.systemui.SysuiTestCase
import com.android.systemui.controls.controller.AuxiliaryPersistenceWrapperTest.Companion.any
import com.android.systemui.statusbar.notification.collection.NotificationEntry
@@ -108,6 +111,28 @@
}
@Test
+ @DisableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON)
+ fun testCreateIcons_chipNotifIconFlagDisabled_statusBarChipIconIsNull() {
+ val entry =
+ notificationEntry(hasShortcut = true, hasMessageSenderIcon = true, hasLargeIcon = true)
+ entry?.let { iconManager.createIcons(it) }
+ testScope.runCurrent()
+
+ assertThat(entry?.icons?.statusBarChipIcon).isNull()
+ }
+
+ @Test
+ @EnableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON)
+ fun testCreateIcons_chipNotifIconFlagEnabled_statusBarChipIconIsNull() {
+ val entry =
+ notificationEntry(hasShortcut = true, hasMessageSenderIcon = true, hasLargeIcon = true)
+ entry?.let { iconManager.createIcons(it) }
+ testScope.runCurrent()
+
+ assertThat(entry?.icons?.statusBarChipIcon).isNotNull()
+ }
+
+ @Test
fun testCreateIcons_importantConversation_shortcutIcon() {
val entry =
notificationEntry(hasShortcut = true, hasMessageSenderIcon = true, hasLargeIcon = true)
@@ -179,6 +204,7 @@
}
@Test
+ @EnableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON)
fun testCreateIcons_sensitiveImportantConversation() {
val entry =
notificationEntry(hasShortcut = true, hasMessageSenderIcon = true, hasLargeIcon = false)
@@ -187,11 +213,13 @@
entry?.let { iconManager.createIcons(it) }
testScope.runCurrent()
assertThat(entry?.icons?.statusBarIcon?.sourceIcon).isEqualTo(shortcutIc)
+ assertThat(entry?.icons?.statusBarChipIcon?.sourceIcon).isEqualTo(shortcutIc)
assertThat(entry?.icons?.shelfIcon?.sourceIcon).isEqualTo(smallIc)
assertThat(entry?.icons?.aodIcon?.sourceIcon).isEqualTo(smallIc)
}
@Test
+ @EnableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON)
fun testUpdateIcons_sensitiveImportantConversation() {
val entry =
notificationEntry(hasShortcut = true, hasMessageSenderIcon = true, hasLargeIcon = false)
@@ -202,6 +230,7 @@
entry?.let { iconManager.updateIcons(it) }
testScope.runCurrent()
assertThat(entry?.icons?.statusBarIcon?.sourceIcon).isEqualTo(shortcutIc)
+ assertThat(entry?.icons?.statusBarChipIcon?.sourceIcon).isEqualTo(shortcutIc)
assertThat(entry?.icons?.shelfIcon?.sourceIcon).isEqualTo(smallIc)
assertThat(entry?.icons?.aodIcon?.sourceIcon).isEqualTo(smallIc)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt
index f9509d2..d1b1f46 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt
@@ -17,6 +17,9 @@
package com.android.systemui.statusbar.notification.interruption
import android.Manifest.permission
+import android.app.Notification.CATEGORY_ALARM
+import android.app.Notification.CATEGORY_CAR_EMERGENCY
+import android.app.Notification.CATEGORY_CAR_WARNING
import android.app.Notification.CATEGORY_EVENT
import android.app.Notification.CATEGORY_REMINDER
import android.app.NotificationManager
@@ -256,6 +259,61 @@
}
@Test
+ fun testAvalancheFilter_duringAvalanche_allowCategoryAlarm() {
+ avalancheProvider.startTime = whenAgo(10)
+
+ withFilter(
+ AvalancheSuppressor(avalancheProvider, systemClock, settingsInteractor, packageManager,
+ uiEventLogger, context, notificationManager)
+ ) {
+ ensurePeekState()
+ assertShouldHeadsUp(
+ buildEntry {
+ importance = NotificationManager.IMPORTANCE_HIGH
+ category = CATEGORY_ALARM
+ }
+ )
+ }
+ }
+
+ @Test
+ fun testAvalancheFilter_duringAvalanche_allowCategoryCarEmergency() {
+ avalancheProvider.startTime = whenAgo(10)
+
+ withFilter(
+ AvalancheSuppressor(avalancheProvider, systemClock, settingsInteractor, packageManager,
+ uiEventLogger, context, notificationManager)
+ ) {
+ ensurePeekState()
+ assertShouldHeadsUp(
+ buildEntry {
+ importance = NotificationManager.IMPORTANCE_HIGH
+ category = CATEGORY_CAR_EMERGENCY
+
+ }
+ )
+ }
+ }
+
+ @Test
+ fun testAvalancheFilter_duringAvalanche_allowCategoryCarWarning() {
+ avalancheProvider.startTime = whenAgo(10)
+
+ withFilter(
+ AvalancheSuppressor(avalancheProvider, systemClock, settingsInteractor, packageManager,
+ uiEventLogger, context, notificationManager)
+ ) {
+ ensurePeekState()
+ assertShouldHeadsUp(
+ buildEntry {
+ importance = NotificationManager.IMPORTANCE_HIGH
+ category = CATEGORY_CAR_WARNING
+ }
+ )
+ }
+ }
+
+ @Test
fun testAvalancheFilter_duringAvalanche_allowFsi() {
avalancheProvider.startTime = whenAgo(10)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt
index 54a26f7..3f28164 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.row
import android.app.Notification
+import android.app.Person
import android.content.Context
import android.os.AsyncTask
import android.os.Build
@@ -39,6 +40,7 @@
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationCallback
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag
import com.android.systemui.statusbar.notification.row.shared.HeadsUpStatusBarModel
@@ -561,6 +563,40 @@
verify(row, times(0)).onNotificationUpdated()
}
+ // TODO b/356709333: Add screenshot tests for these views
+ @Test
+ fun testInflatePublicSingleLineView() {
+ row.publicLayout.removeAllViews()
+ inflateAndWait(false, notificationInflater, FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE, row)
+ Assert.assertNotNull(row.publicLayout.mSingleLineView)
+ Assert.assertTrue(row.publicLayout.mSingleLineView is HybridNotificationView)
+ }
+
+ @Test
+ fun testInflatePublicSingleLineConversationView() {
+ val testPerson = Person.Builder().setName("Person").build()
+ val messagingBuilder =
+ Notification.Builder(mContext, "no-id")
+ .setSmallIcon(R.drawable.ic_person)
+ .setContentTitle("Title")
+ .setContentText("Text")
+ .setStyle(Notification.MessagingStyle(testPerson))
+
+ val messagingRow = spy(testHelper.createRow(messagingBuilder.build()))
+ messagingRow.publicLayout.removeAllViews()
+ inflateAndWait(
+ false,
+ notificationInflater,
+ FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE,
+ messagingRow
+ )
+ Assert.assertNotNull(messagingRow.publicLayout.mSingleLineView)
+ // assert this is the conversation layout
+ Assert.assertTrue(
+ messagingRow.publicLayout.mSingleLineView is HybridConversationNotificationView
+ )
+ }
+
private class ExceptionHolder {
var exception: Exception? = null
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index d7fdce2..75376e6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -620,8 +620,12 @@
.setUser(userHandle)
.setPostTime(System.currentTimeMillis())
.setChannel(channel)
+ .updateRanking(rankingBuilder -> rankingBuilder.setIsConversation(
+ notification.isStyle(Notification.MessagingStyle.class)
+ ))
.build();
+
return generateRow(entry, extraInflationFlags);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineConversationViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineConversationViewBinderTest.kt
deleted file mode 100644
index 53a1198..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineConversationViewBinderTest.kt
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.statusbar.notification.row
-
-import android.app.Notification
-import android.app.Person
-import android.platform.test.annotations.EnableFlags
-import android.testing.TestableLooper
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.internal.R
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_SINGLE_LINE
-import com.android.systemui.statusbar.notification.row.SingleLineViewInflater.inflateSingleLineViewHolder
-import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation
-import com.android.systemui.statusbar.notification.row.ui.viewbinder.SingleLineConversationViewBinder
-import com.android.systemui.util.mockito.mock
-import kotlin.test.assertEquals
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-@TestableLooper.RunWithLooper
-class SingleLineConversationViewBinderTest : SysuiTestCase() {
- private lateinit var notificationBuilder: Notification.Builder
- private lateinit var helper: NotificationTestHelper
-
- @Before
- fun setUp() {
- allowTestableLooperAsMainThread()
- helper = NotificationTestHelper(context, mDependency, TestableLooper.get(this))
- notificationBuilder = Notification.Builder(context, CHANNEL_ID)
- notificationBuilder
- .setSmallIcon(R.drawable.ic_corp_icon)
- .setContentTitle(CONTENT_TITLE)
- .setContentText(CONTENT_TEXT)
- }
-
- @Test
- @EnableFlags(AsyncHybridViewInflation.FLAG_NAME)
- fun bindGroupConversationSingleLineView() {
- // GIVEN a row with a group conversation notification
- val user =
- Person.Builder()
- // .setIcon(Icon.createWithResource(mContext,
- // R.drawable.ic_account_circle))
- .setName(USER_NAME)
- .build()
- val style =
- Notification.MessagingStyle(user)
- .addMessage(MESSAGE_TEXT, System.currentTimeMillis(), user)
- .addMessage(
- "How about lunch?",
- System.currentTimeMillis(),
- Person.Builder().setName("user2").build()
- )
- .setGroupConversation(true)
- notificationBuilder.setStyle(style).setShortcutId(SHORTCUT_ID)
- val notification = notificationBuilder.build()
- val row = helper.createRow(notification)
-
- val viewHolder =
- inflateSingleLineViewHolder(
- isConversation = true,
- reinflateFlags = FLAG_CONTENT_VIEW_SINGLE_LINE,
- entry = row.entry,
- context = context,
- logger = mock()
- )
- as HybridConversationNotificationView
- val viewModel =
- SingleLineViewInflater.inflateSingleLineViewModel(
- notification = notification,
- messagingStyle = style,
- builder = notificationBuilder,
- systemUiContext = context,
- )
- // WHEN: binds the viewHolder
- SingleLineConversationViewBinder.bind(
- viewModel,
- viewHolder,
- )
-
- // THEN: the single-line conversation view should be bind with view model's corresponding
- // fields
- assertEquals(viewModel.titleText, viewHolder.titleView.text)
- assertEquals(viewModel.contentText, viewHolder.textView.text)
- assertEquals(
- viewModel.conversationData?.conversationSenderName,
- viewHolder.conversationSenderNameView.text
- )
- }
-
- private companion object {
- const val CHANNEL_ID = "CHANNEL_ID"
- const val CONTENT_TITLE = "CONTENT_TITLE"
- const val CONTENT_TEXT = "CONTENT_TEXT"
- const val USER_NAME = "USER_NAME"
- const val MESSAGE_TEXT = "MESSAGE_TEXT"
- const val SHORTCUT_ID = "Shortcut"
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt
index ee819c4..6b3fb5b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt
@@ -16,18 +16,22 @@
package com.android.systemui.statusbar.notification.row
import android.app.Notification
+import android.app.Person
import android.platform.test.annotations.EnableFlags
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_SINGLE_LINE
-import com.android.systemui.statusbar.notification.row.SingleLineViewInflater.inflateSingleLineViewHolder
+import com.android.systemui.statusbar.notification.row.SingleLineViewInflater.inflatePrivateSingleLineView
+import com.android.systemui.statusbar.notification.row.SingleLineViewInflater.inflatePublicSingleLineView
import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation
import com.android.systemui.statusbar.notification.row.ui.viewbinder.SingleLineViewBinder
import com.android.systemui.util.mockito.mock
-import org.junit.Assert
+import kotlin.test.assertEquals
+import kotlin.test.assertNotNull
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -59,14 +63,25 @@
val notification = notificationBuilder.build()
val row: ExpandableNotificationRow = helper.createRow(notification)
- val viewHolder =
- inflateSingleLineViewHolder(
+ val view =
+ inflatePrivateSingleLineView(
isConversation = false,
reinflateFlags = FLAG_CONTENT_VIEW_SINGLE_LINE,
entry = row.entry,
context = context,
logger = mock()
)
+
+ val publicView =
+ inflatePublicSingleLineView(
+ isConversation = false,
+ reinflateFlags = FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE,
+ entry = row.entry,
+ context = context,
+ logger = mock()
+ )
+ assertNotNull(publicView)
+
val viewModel =
SingleLineViewInflater.inflateSingleLineViewModel(
notification = notification,
@@ -76,16 +91,86 @@
)
// WHEN: binds the viewHolder
- SingleLineViewBinder.bind(viewModel, viewHolder)
+ SingleLineViewBinder.bind(viewModel, view)
// THEN: the single-line view should be bind with viewModel's title and content text
- Assert.assertEquals(viewModel.titleText, viewHolder?.titleView?.text)
- Assert.assertEquals(viewModel.contentText, viewHolder?.textView?.text)
+ assertEquals(viewModel.titleText, view?.titleView?.text)
+ assertEquals(viewModel.contentText, view?.textView?.text)
+ }
+
+ @Test
+ @EnableFlags(AsyncHybridViewInflation.FLAG_NAME)
+ fun bindGroupConversationSingleLineView() {
+ // GIVEN a row with a group conversation notification
+ val user =
+ Person.Builder()
+ // .setIcon(Icon.createWithResource(mContext,
+ // R.drawable.ic_account_circle))
+ .setName(USER_NAME)
+ .build()
+ val style =
+ Notification.MessagingStyle(user)
+ .addMessage(MESSAGE_TEXT, System.currentTimeMillis(), user)
+ .addMessage(
+ "How about lunch?",
+ System.currentTimeMillis(),
+ Person.Builder().setName("user2").build()
+ )
+ .setGroupConversation(true)
+ notificationBuilder.setStyle(style).setShortcutId(SHORTCUT_ID)
+ val notification = notificationBuilder.build()
+ val row = helper.createRow(notification)
+
+ val view =
+ inflatePrivateSingleLineView(
+ isConversation = true,
+ reinflateFlags = FLAG_CONTENT_VIEW_SINGLE_LINE,
+ entry = row.entry,
+ context = context,
+ logger = mock()
+ )
+ as HybridConversationNotificationView
+
+ val publicView =
+ inflatePublicSingleLineView(
+ isConversation = true,
+ reinflateFlags = FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE,
+ entry = row.entry,
+ context = context,
+ logger = mock()
+ )
+ as HybridConversationNotificationView
+ assertNotNull(publicView)
+
+ val viewModel =
+ SingleLineViewInflater.inflateSingleLineViewModel(
+ notification = notification,
+ messagingStyle = style,
+ builder = notificationBuilder,
+ systemUiContext = context,
+ )
+ // WHEN: binds the view
+ SingleLineViewBinder.bind(
+ viewModel,
+ view,
+ )
+
+ // THEN: the single-line conversation view should be bound with view model's corresponding
+ // fields
+ assertEquals(viewModel.titleText, view.titleView.text)
+ assertEquals(viewModel.contentText, view.textView.text)
+ assertEquals(
+ viewModel.conversationData?.conversationSenderName,
+ view.conversationSenderNameView.text
+ )
}
private companion object {
const val CHANNEL_ID = "CHANNEL_ID"
const val CONTENT_TITLE = "A Cool New Feature"
const val CONTENT_TEXT = "Checkout out new feature!"
+ const val USER_NAME = "USER_NAME"
+ const val MESSAGE_TEXT = "MESSAGE_TEXT"
+ const val SHORTCUT_ID = "Shortcut"
}
}
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 b799595..22b9887 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
@@ -77,7 +77,10 @@
import com.android.systemui.flags.FakeFeatureFlags;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
+import com.android.systemui.qs.flags.NewQsUI;
+import com.android.systemui.qs.flags.QSComposeFragment;
import com.android.systemui.res.R;
+import com.android.systemui.shade.QSHeaderBoundsProvider;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
import com.android.systemui.statusbar.EmptyShadeView;
@@ -99,6 +102,8 @@
import com.android.systemui.statusbar.policy.AvalancheController;
import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController;
+import kotlin.Unit;
+
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
@@ -807,6 +812,7 @@
}
@Test
+ @DisableFlags({QSComposeFragment.FLAG_NAME, NewQsUI.FLAG_NAME})
@DisableSceneContainer // TODO(b/312473478): address lack of QS Header
public void testInsideQSHeader_noOffset() {
ViewGroup qsHeader = mock(ViewGroup.class);
@@ -824,6 +830,7 @@
}
@Test
+ @DisableFlags({QSComposeFragment.FLAG_NAME, NewQsUI.FLAG_NAME})
@DisableSceneContainer // TODO(b/312473478): address lack of QS Header
public void testInsideQSHeader_Offset() {
ViewGroup qsHeader = mock(ViewGroup.class);
@@ -844,6 +851,63 @@
}
@Test
+ @EnableFlags({QSComposeFragment.FLAG_NAME, NewQsUI.FLAG_NAME})
+ @DisableSceneContainer // TODO(b/312473478): address lack of QS Header
+ public void testInsideQSHeader_noOffset_qsCompose() {
+ ViewGroup qsHeader = mock(ViewGroup.class);
+ Rect boundsOnScreen = new Rect(0, 0, 1000, 1000);
+ mockBoundsOnScreen(qsHeader, boundsOnScreen);
+
+ QSHeaderBoundsProvider provider = new QSHeaderBoundsProvider(
+ () -> 0,
+ boundsOnScreen::height,
+ rect -> {
+ qsHeader.getBoundsOnScreen(rect);
+ return Unit.INSTANCE;
+ }
+ );
+
+ mStackScroller.setQsHeaderBoundsProvider(provider);
+ mStackScroller.setLeftTopRightBottom(0, 0, 2000, 2000);
+
+ MotionEvent event1 = transformEventForView(createMotionEvent(100f, 100f), mStackScroller);
+ assertTrue(mStackScroller.isInsideQsHeader(event1));
+
+ MotionEvent event2 = transformEventForView(createMotionEvent(1100f, 100f), mStackScroller);
+ assertFalse(mStackScroller.isInsideQsHeader(event2));
+ }
+
+ @Test
+ @EnableFlags({QSComposeFragment.FLAG_NAME, NewQsUI.FLAG_NAME})
+ @DisableSceneContainer // TODO(b/312473478): address lack of QS Header
+ public void testInsideQSHeader_Offset_qsCompose() {
+ ViewGroup qsHeader = mock(ViewGroup.class);
+ Rect boundsOnScreen = new Rect(100, 100, 1000, 1000);
+ mockBoundsOnScreen(qsHeader, boundsOnScreen);
+
+ QSHeaderBoundsProvider provider = new QSHeaderBoundsProvider(
+ () -> 0,
+ boundsOnScreen::height,
+ rect -> {
+ qsHeader.getBoundsOnScreen(rect);
+ return Unit.INSTANCE;
+ }
+ );
+
+ mStackScroller.setQsHeaderBoundsProvider(provider);
+ mStackScroller.setLeftTopRightBottom(200, 200, 2000, 2000);
+
+ MotionEvent event1 = transformEventForView(createMotionEvent(50f, 50f), mStackScroller);
+ assertFalse(mStackScroller.isInsideQsHeader(event1));
+
+ MotionEvent event2 = transformEventForView(createMotionEvent(150f, 150f), mStackScroller);
+ assertFalse(mStackScroller.isInsideQsHeader(event2));
+
+ MotionEvent event3 = transformEventForView(createMotionEvent(250f, 250f), mStackScroller);
+ assertTrue(mStackScroller.isInsideQsHeader(event3));
+ }
+
+ @Test
@DisableSceneContainer // TODO(b/312473478): address disabled test
public void setFractionToShade_recomputesStackHeight() {
mStackScroller.setFractionToShade(1f);
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 bd9cccd..a6b2729 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
@@ -1157,22 +1157,13 @@
}
@Test
- @EnableFlags(com.android.systemui.Flags.FLAG_TRUNCATED_STATUS_BAR_ICONS_FIX)
- public void updateResources_flagEnabled_doesNotUpdateStatusBarWindowHeight() {
+ public void updateResources_doesNotUpdateStatusBarWindowHeight() {
mCentralSurfaces.updateResources();
verify(mStatusBarWindowController, never()).refreshStatusBarHeight();
}
@Test
- @DisableFlags(com.android.systemui.Flags.FLAG_TRUNCATED_STATUS_BAR_ICONS_FIX)
- public void updateResources_flagDisabled_updatesStatusBarWindowHeight() {
- mCentralSurfaces.updateResources();
-
- verify(mStatusBarWindowController).refreshStatusBarHeight();
- }
-
- @Test
@EnableSceneContainer
public void brightnesShowingChanged_flagEnabled_ScrimControllerNotified() {
mCentralSurfaces.registerCallbacks();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
index e670884..eae4f23 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
@@ -30,7 +30,6 @@
import android.view.WindowInsets
import android.widget.FrameLayout
import androidx.test.filters.SmallTest
-import com.android.systemui.Flags
import com.android.systemui.Gefingerpoken
import com.android.systemui.SysuiTestCase
import com.android.systemui.plugins.DarkIconDispatcher
@@ -41,7 +40,6 @@
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
-import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
@@ -123,36 +121,21 @@
}
@Test
- fun onAttachedToWindow_flagEnabled_updatesWindowHeight() {
- mSetFlagsRule.enableFlags(Flags.FLAG_TRUNCATED_STATUS_BAR_ICONS_FIX)
-
+ fun onAttachedToWindow_updatesWindowHeight() {
view.onAttachedToWindow()
verify(windowController).refreshStatusBarHeight()
}
@Test
- fun onAttachedToWindow_flagDisabled_doesNotUpdateWindowHeight() {
- mSetFlagsRule.disableFlags(Flags.FLAG_TRUNCATED_STATUS_BAR_ICONS_FIX)
-
- view.onAttachedToWindow()
-
- verify(windowController, never()).refreshStatusBarHeight()
- }
-
- @Test
- fun onConfigurationChanged_flagEnabled_updatesWindowHeight() {
- mSetFlagsRule.enableFlags(Flags.FLAG_TRUNCATED_STATUS_BAR_ICONS_FIX)
-
+ fun onConfigurationChanged_updatesWindowHeight() {
view.onConfigurationChanged(Configuration())
verify(windowController).refreshStatusBarHeight()
}
@Test
- fun onConfigurationChanged_multipleCalls_flagEnabled_updatesWindowHeightMultipleTimes() {
- mSetFlagsRule.enableFlags(Flags.FLAG_TRUNCATED_STATUS_BAR_ICONS_FIX)
-
+ fun onConfigurationChanged_multipleCalls_updatesWindowHeightMultipleTimes() {
view.onConfigurationChanged(Configuration())
view.onConfigurationChanged(Configuration())
view.onConfigurationChanged(Configuration())
@@ -162,29 +145,8 @@
}
@Test
- fun onConfigurationChanged_flagDisabled_doesNotUpdateWindowHeight() {
- mSetFlagsRule.disableFlags(Flags.FLAG_TRUNCATED_STATUS_BAR_ICONS_FIX)
-
- view.onConfigurationChanged(Configuration())
-
- verify(windowController, never()).refreshStatusBarHeight()
- }
-
- @Test
- fun onConfigurationChanged_multipleCalls_flagDisabled_doesNotUpdateWindowHeight() {
- mSetFlagsRule.disableFlags(Flags.FLAG_TRUNCATED_STATUS_BAR_ICONS_FIX)
-
- view.onConfigurationChanged(Configuration())
- view.onConfigurationChanged(Configuration())
- view.onConfigurationChanged(Configuration())
- view.onConfigurationChanged(Configuration())
-
- verify(windowController, never()).refreshStatusBarHeight()
- }
-
- @Test
fun onAttachedToWindow_updatesLeftTopRightPaddingsBasedOnInsets() {
- val insets = Insets.of(/* left = */ 10, /* top = */ 20, /* right = */ 30, /* bottom = */ 40)
+ val insets = Insets.of(/* left= */ 10, /* top= */ 20, /* right= */ 30, /* bottom= */ 40)
whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
.thenReturn(insets)
@@ -198,7 +160,7 @@
@Test
fun onConfigurationChanged_updatesLeftTopRightPaddingsBasedOnInsets() {
- val insets = Insets.of(/* left = */ 40, /* top = */ 30, /* right = */ 20, /* bottom = */ 10)
+ val insets = Insets.of(/* left= */ 40, /* top= */ 30, /* right= */ 20, /* bottom= */ 10)
whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
.thenReturn(insets)
@@ -213,7 +175,7 @@
@Test
fun onConfigurationChanged_noRelevantChange_doesNotUpdateInsets() {
val previousInsets =
- Insets.of(/* left = */ 40, /* top = */ 30, /* right = */ 20, /* bottom = */ 10)
+ Insets.of(/* left= */ 40, /* top= */ 30, /* right= */ 20, /* bottom= */ 10)
whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
.thenReturn(previousInsets)
context.orCreateTestableResources.overrideConfiguration(Configuration())
@@ -233,7 +195,7 @@
@Test
fun onConfigurationChanged_densityChanged_updatesInsets() {
val previousInsets =
- Insets.of(/* left = */ 40, /* top = */ 30, /* right = */ 20, /* bottom = */ 10)
+ Insets.of(/* left= */ 40, /* top= */ 30, /* right= */ 20, /* bottom= */ 10)
whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
.thenReturn(previousInsets)
val configuration = Configuration()
@@ -256,7 +218,7 @@
@Test
fun onConfigurationChanged_fontScaleChanged_updatesInsets() {
val previousInsets =
- Insets.of(/* left = */ 40, /* top = */ 30, /* right = */ 20, /* bottom = */ 10)
+ Insets.of(/* left= */ 40, /* top= */ 30, /* right= */ 20, /* bottom= */ 10)
whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
.thenReturn(previousInsets)
val configuration = Configuration()
@@ -291,7 +253,7 @@
@Test
fun onApplyWindowInsets_updatesLeftTopRightPaddingsBasedOnInsets() {
- val insets = Insets.of(/* left = */ 90, /* top = */ 10, /* right = */ 45, /* bottom = */ 50)
+ val insets = Insets.of(/* left= */ 90, /* top= */ 10, /* right= */ 45, /* bottom= */ 50)
whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
.thenReturn(insets)
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 9b61105..af5e60e 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
@@ -1068,7 +1068,7 @@
public void testShowBouncerOrKeyguard_needsFullScreen() {
when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(
KeyguardSecurityModel.SecurityMode.SimPin);
- mStatusBarKeyguardViewManager.showBouncerOrKeyguard(false, false);
+ mStatusBarKeyguardViewManager.showBouncerOrKeyguard(false);
verify(mCentralSurfaces).hideKeyguard();
verify(mPrimaryBouncerInteractor).show(true);
}
@@ -1084,7 +1084,7 @@
.thenReturn(KeyguardState.LOCKSCREEN);
reset(mCentralSurfaces);
- mStatusBarKeyguardViewManager.showBouncerOrKeyguard(false, false);
+ mStatusBarKeyguardViewManager.showBouncerOrKeyguard(false);
verify(mPrimaryBouncerInteractor).show(true);
verify(mCentralSurfaces).showKeyguard();
}
@@ -1092,26 +1092,11 @@
@Test
@DisableSceneContainer
public void testShowBouncerOrKeyguard_needsFullScreen_bouncerAlreadyShowing() {
- boolean isFalsingReset = false;
when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(
KeyguardSecurityModel.SecurityMode.SimPin);
when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(true);
- mStatusBarKeyguardViewManager.showBouncerOrKeyguard(false, isFalsingReset);
+ mStatusBarKeyguardViewManager.showBouncerOrKeyguard(false);
verify(mCentralSurfaces, never()).hideKeyguard();
- verify(mPrimaryBouncerInteractor).show(true);
- }
-
- @Test
- @DisableSceneContainer
- public void testShowBouncerOrKeyguard_needsFullScreen_bouncerAlreadyShowing_onFalsing() {
- boolean isFalsingReset = true;
- when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(
- KeyguardSecurityModel.SecurityMode.SimPin);
- when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(true);
- mStatusBarKeyguardViewManager.showBouncerOrKeyguard(false, isFalsingReset);
- verify(mCentralSurfaces, never()).hideKeyguard();
-
- // Do not refresh the full screen bouncer if the call is from falsing
verify(mPrimaryBouncerInteractor, never()).show(true);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaListenerTest.kt
similarity index 97%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaListenerTest.kt
index c4371fd..597e2e4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaListenerTest.kt
@@ -32,9 +32,11 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_STATUS_BAR_SCREEN_SHARING_CHIPS
+import com.android.systemui.Flags.FLAG_STATUS_BAR_USE_REPOS_FOR_CALL_CHIP
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.res.R
@@ -44,6 +46,7 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
+import com.android.systemui.statusbar.notification.domain.interactor.activeNotificationsInteractor
import com.android.systemui.statusbar.phone.ongoingcall.data.repository.ongoingCallRepository
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel
import com.android.systemui.statusbar.window.StatusBarWindowController
@@ -84,7 +87,8 @@
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
@OptIn(ExperimentalCoroutinesApi::class)
-class OngoingCallControllerTest : SysuiTestCase() {
+@DisableFlags(FLAG_STATUS_BAR_USE_REPOS_FOR_CALL_CHIP)
+class OngoingCallControllerViaListenerTest : SysuiTestCase() {
private val kosmos = Kosmos()
private val clock = FakeSystemClock()
@@ -121,6 +125,7 @@
context,
ongoingCallRepository,
notificationCollection,
+ kosmos.activeNotificationsInteractor,
clock,
mockActivityStarter,
mainExecutor,
@@ -129,7 +134,7 @@
mockStatusBarWindowController,
mockSwipeStatusBarAwayGestureHandler,
statusBarModeRepository,
- logcatLogBuffer("OngoingCallControllerTest"),
+ logcatLogBuffer("OngoingCallControllerViaListenerTest"),
)
controller.start()
controller.addCallback(mockOngoingCallListener)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaRepoTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaRepoTest.kt
new file mode 100644
index 0000000..dfe01bf
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaRepoTest.kt
@@ -0,0 +1,711 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone.ongoingcall
+
+import android.app.ActivityManager
+import android.app.IActivityManager
+import android.app.IUidObserver
+import android.app.PendingIntent
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
+import android.testing.TestableLooper
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.LinearLayout
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.Flags.FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON
+import com.android.systemui.Flags.FLAG_STATUS_BAR_SCREEN_SHARING_CHIPS
+import com.android.systemui.Flags.FLAG_STATUS_BAR_USE_REPOS_FOR_CALL_CHIP
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.concurrency.fakeExecutor
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.log.logcatLogBuffer
+import com.android.systemui.plugins.activityStarter
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.StatusBarIconView
+import com.android.systemui.statusbar.data.repository.fakeStatusBarModeRepository
+import com.android.systemui.statusbar.gesture.SwipeStatusBarAwayGestureHandler
+import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
+import com.android.systemui.statusbar.notification.data.model.activeNotificationModel
+import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore
+import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
+import com.android.systemui.statusbar.notification.domain.interactor.activeNotificationsInteractor
+import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
+import com.android.systemui.statusbar.notification.shared.CallType
+import com.android.systemui.statusbar.phone.ongoingcall.data.repository.ongoingCallRepository
+import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel
+import com.android.systemui.statusbar.window.StatusBarWindowController
+import com.android.systemui.util.time.fakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.argumentCaptor
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.never
+import org.mockito.kotlin.reset
+import org.mockito.kotlin.times
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@TestableLooper.RunWithLooper
+@OptIn(ExperimentalCoroutinesApi::class)
+@EnableFlags(FLAG_STATUS_BAR_USE_REPOS_FOR_CALL_CHIP)
+class OngoingCallControllerViaRepoTest : SysuiTestCase() {
+ private val kosmos = Kosmos()
+
+ private val clock = kosmos.fakeSystemClock
+ private val mainExecutor = kosmos.fakeExecutor
+ private val testScope = kosmos.testScope
+ private val statusBarModeRepository = kosmos.fakeStatusBarModeRepository
+ private val ongoingCallRepository = kosmos.ongoingCallRepository
+ private val activeNotificationListRepository = kosmos.activeNotificationListRepository
+
+ private lateinit var controller: OngoingCallController
+
+ private val mockSwipeStatusBarAwayGestureHandler = mock<SwipeStatusBarAwayGestureHandler>()
+ private val mockOngoingCallListener = mock<OngoingCallListener>()
+ private val mockActivityStarter = kosmos.activityStarter
+ private val mockIActivityManager = mock<IActivityManager>()
+ private val mockStatusBarWindowController = mock<StatusBarWindowController>()
+
+ private lateinit var chipView: View
+
+ @Before
+ fun setUp() {
+ allowTestableLooperAsMainThread()
+ TestableLooper.get(this).runWithLooper {
+ chipView = LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip, null)
+ }
+
+ controller =
+ OngoingCallController(
+ testScope.backgroundScope,
+ context,
+ ongoingCallRepository,
+ mock<CommonNotifCollection>(),
+ kosmos.activeNotificationsInteractor,
+ clock,
+ mockActivityStarter,
+ mainExecutor,
+ mockIActivityManager,
+ DumpManager(),
+ mockStatusBarWindowController,
+ mockSwipeStatusBarAwayGestureHandler,
+ statusBarModeRepository,
+ logcatLogBuffer("OngoingCallControllerViaRepoTest"),
+ )
+ controller.start()
+ controller.addCallback(mockOngoingCallListener)
+ controller.setChipView(chipView)
+
+ // Let the controller get the starting value from activeNotificationsInteractor
+ testScope.runCurrent()
+ reset(mockOngoingCallListener)
+
+ whenever(
+ mockIActivityManager.getUidProcessState(
+ eq(CALL_UID),
+ any(),
+ )
+ )
+ .thenReturn(PROC_STATE_INVISIBLE)
+ }
+
+ @After
+ fun tearDown() {
+ controller.tearDownChipView()
+ }
+
+ @Test
+ fun interactorHasOngoingCallNotif_listenerAndRepoNotified() =
+ testScope.runTest {
+ setNotifOnRepo(
+ activeNotificationModel(
+ key = "ongoingNotif",
+ callType = CallType.Ongoing,
+ uid = CALL_UID,
+ whenTime = 567,
+ )
+ )
+
+ verify(mockOngoingCallListener).onOngoingCallStateChanged(any())
+ val repoState = ongoingCallRepository.ongoingCallState.value
+ assertThat(repoState).isInstanceOf(OngoingCallModel.InCall::class.java)
+ assertThat((repoState as OngoingCallModel.InCall).startTimeMs).isEqualTo(567)
+ }
+
+ @Test
+ @DisableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON)
+ fun interactorHasOngoingCallNotif_notifIconFlagOff_repoHasNoNotifIcon() =
+ testScope.runTest {
+ val icon = mock<StatusBarIconView>()
+ setNotifOnRepo(
+ activeNotificationModel(
+ key = "ongoingNotif",
+ callType = CallType.Ongoing,
+ uid = CALL_UID,
+ statusBarChipIcon = icon,
+ whenTime = 567,
+ )
+ )
+
+ val repoState = ongoingCallRepository.ongoingCallState.value
+ assertThat(repoState).isInstanceOf(OngoingCallModel.InCall::class.java)
+ assertThat((repoState as OngoingCallModel.InCall).notificationIconView).isNull()
+ }
+
+ @Test
+ @EnableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON)
+ fun interactorHasOngoingCallNotif_notifIconFlagOn_repoHasNotifIcon() =
+ testScope.runTest {
+ val icon = mock<StatusBarIconView>()
+
+ setNotifOnRepo(
+ activeNotificationModel(
+ key = "ongoingNotif",
+ callType = CallType.Ongoing,
+ uid = CALL_UID,
+ statusBarChipIcon = icon,
+ whenTime = 567,
+ )
+ )
+
+ val repoState = ongoingCallRepository.ongoingCallState.value
+ assertThat(repoState).isInstanceOf(OngoingCallModel.InCall::class.java)
+ assertThat((repoState as OngoingCallModel.InCall).notificationIconView).isEqualTo(icon)
+ }
+
+ @Test
+ fun notifRepoHasOngoingCallNotif_isOngoingCallNotif_windowControllerUpdated() {
+ setCallNotifOnRepo()
+
+ verify(mockStatusBarWindowController).setOngoingProcessRequiresStatusBarVisible(true)
+ }
+
+ @Test
+ fun notifRepoHasNoCallNotif_listenerAndRepoNotNotified() {
+ setNoNotifsOnRepo()
+
+ verify(mockOngoingCallListener, never()).onOngoingCallStateChanged(any())
+ assertThat(ongoingCallRepository.ongoingCallState.value)
+ .isInstanceOf(OngoingCallModel.NoCall::class.java)
+ }
+
+ @Test
+ fun notifRepoHasOngoingCallNotifThenScreeningNotif_listenerNotifiedTwice() {
+ setNotifOnRepo(
+ activeNotificationModel(
+ key = "notif",
+ callType = CallType.Ongoing,
+ )
+ )
+
+ setNotifOnRepo(
+ activeNotificationModel(
+ key = "notif",
+ callType = CallType.Screening,
+ )
+ )
+
+ verify(mockOngoingCallListener, times(2)).onOngoingCallStateChanged(any())
+ }
+
+ @Test
+ fun notifRepoHasOngoingCallNotifThenScreeningNotif_repoUpdated() {
+ setNotifOnRepo(
+ activeNotificationModel(
+ key = "notif",
+ callType = CallType.Ongoing,
+ )
+ )
+
+ setNotifOnRepo(
+ activeNotificationModel(
+ key = "notif",
+ callType = CallType.Screening,
+ )
+ )
+
+ assertThat(ongoingCallRepository.ongoingCallState.value)
+ .isInstanceOf(OngoingCallModel.NoCall::class.java)
+ }
+
+ /** Regression test for b/191472854. */
+ @Test
+ fun notifRepoHasCallNotif_notifHasNullContentIntent_noCrash() {
+ setNotifOnRepo(
+ activeNotificationModel(
+ key = "notif",
+ callType = CallType.Ongoing,
+ contentIntent = null,
+ )
+ )
+ }
+
+ /** Regression test for b/192379214. */
+ @Test
+ @DisableFlags(android.app.Flags.FLAG_SORT_SECTION_BY_TIME, FLAG_STATUS_BAR_SCREEN_SHARING_CHIPS)
+ fun notifRepoHasCallNotif_notificationWhenIsZero_timeHidden() {
+ setNotifOnRepo(
+ activeNotificationModel(
+ key = "notif",
+ callType = CallType.Ongoing,
+ contentIntent = null,
+ whenTime = 0,
+ )
+ )
+
+ chipView.measure(
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
+ )
+
+ assertThat(chipView.findViewById<View>(R.id.ongoing_activity_chip_time)?.measuredWidth)
+ .isEqualTo(0)
+ }
+
+ @Test
+ @DisableFlags(FLAG_STATUS_BAR_SCREEN_SHARING_CHIPS)
+ fun notifRepoHasCallNotif_notificationWhenIsValid_timeShown() {
+ setNotifOnRepo(
+ activeNotificationModel(
+ key = "notif",
+ callType = CallType.Ongoing,
+ whenTime = clock.currentTimeMillis(),
+ )
+ )
+
+ chipView.measure(
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
+ )
+
+ assertThat(chipView.findViewById<View>(R.id.ongoing_activity_chip_time)?.measuredWidth)
+ .isGreaterThan(0)
+ }
+
+ /** Regression test for b/194731244. */
+ @Test
+ fun repoHasCallNotif_updatedManyTimes_uidObserverOnlyRegisteredOnce() {
+ for (i in 0 until 4) {
+ // Re-create the notification each time so that it's considered a different object and
+ // will re-trigger the whole flow.
+ setNotifOnRepo(
+ activeNotificationModel(
+ key = "notif$i",
+ callType = CallType.Ongoing,
+ whenTime = 44,
+ )
+ )
+ }
+
+ verify(mockIActivityManager, times(1)).registerUidObserver(any(), any(), any(), any())
+ }
+
+ /** Regression test for b/216248574. */
+ @Test
+ fun repoHasCallNotif_getUidProcessStateThrowsException_noCrash() {
+ whenever(
+ mockIActivityManager.getUidProcessState(
+ eq(CALL_UID),
+ any(),
+ )
+ )
+ .thenThrow(SecurityException())
+
+ // No assert required, just check no crash
+ setCallNotifOnRepo()
+ }
+
+ /** Regression test for b/216248574. */
+ @Test
+ fun repoHasCallNotif_registerUidObserverThrowsException_noCrash() {
+ whenever(
+ mockIActivityManager.registerUidObserver(
+ any(),
+ any(),
+ any(),
+ any(),
+ )
+ )
+ .thenThrow(SecurityException())
+
+ // No assert required, just check no crash
+ setCallNotifOnRepo()
+ }
+
+ /** Regression test for b/216248574. */
+ @Test
+ fun repoHasCallNotif_packageNameProvidedToActivityManager() {
+ setCallNotifOnRepo()
+
+ val packageNameCaptor = argumentCaptor<String>()
+ verify(mockIActivityManager)
+ .registerUidObserver(any(), any(), any(), packageNameCaptor.capture())
+ assertThat(packageNameCaptor.firstValue).isNotNull()
+ }
+
+ @Test
+ fun repo_callNotifAddedThenRemoved_listenerNotified() {
+ setCallNotifOnRepo()
+ reset(mockOngoingCallListener)
+
+ setNoNotifsOnRepo()
+
+ verify(mockOngoingCallListener).onOngoingCallStateChanged(any())
+ }
+
+ @Test
+ fun repo_callNotifAddedThenRemoved_repoUpdated() {
+ setCallNotifOnRepo()
+
+ setNoNotifsOnRepo()
+
+ assertThat(ongoingCallRepository.ongoingCallState.value)
+ .isInstanceOf(OngoingCallModel.NoCall::class.java)
+ }
+
+ @Test
+ fun repo_callNotifAddedThenRemoved_windowControllerUpdated() {
+ reset(mockStatusBarWindowController)
+
+ setCallNotifOnRepo()
+
+ setNoNotifsOnRepo()
+
+ verify(mockStatusBarWindowController).setOngoingProcessRequiresStatusBarVisible(false)
+ }
+
+ @Test
+ fun hasOngoingCall_noOngoingCallNotifSent_returnsFalse() {
+ assertThat(controller.hasOngoingCall()).isFalse()
+ }
+
+ @Test
+ fun hasOngoingCall_repoHasUnrelatedNotif_returnsFalse() {
+ setNotifOnRepo(
+ activeNotificationModel(
+ key = "unrelated",
+ callType = CallType.None,
+ uid = CALL_UID,
+ )
+ )
+
+ assertThat(controller.hasOngoingCall()).isFalse()
+ }
+
+ @Test
+ fun hasOngoingCall_repoHasScreeningCall_returnsFalse() {
+ setNotifOnRepo(
+ activeNotificationModel(
+ key = "unrelated",
+ callType = CallType.Screening,
+ uid = CALL_UID,
+ )
+ )
+
+ assertThat(controller.hasOngoingCall()).isFalse()
+ }
+
+ @Test
+ fun hasOngoingCall_repoHasCallNotifAndCallAppNotVisible_returnsTrue() {
+ whenever(
+ mockIActivityManager.getUidProcessState(
+ eq(CALL_UID),
+ any(),
+ )
+ )
+ .thenReturn(PROC_STATE_INVISIBLE)
+
+ setNotifOnRepo(
+ activeNotificationModel(
+ key = "notif",
+ callType = CallType.Ongoing,
+ uid = CALL_UID,
+ )
+ )
+
+ assertThat(controller.hasOngoingCall()).isTrue()
+ }
+
+ @Test
+ fun hasOngoingCall_repoHasCallNotifButCallAppVisible_returnsFalse() {
+ whenever(mockIActivityManager.getUidProcessState(eq(CALL_UID), any()))
+ .thenReturn(PROC_STATE_VISIBLE)
+
+ setNotifOnRepo(
+ activeNotificationModel(
+ key = "notif",
+ callType = CallType.Ongoing,
+ uid = CALL_UID,
+ )
+ )
+
+ assertThat(controller.hasOngoingCall()).isFalse()
+ }
+
+ @Test
+ fun hasOngoingCall_repoHasCallNotifButInvalidChipView_returnsFalse() {
+ val invalidChipView = LinearLayout(context)
+ controller.setChipView(invalidChipView)
+
+ setNotifOnRepo(
+ activeNotificationModel(
+ key = "notif",
+ callType = CallType.Ongoing,
+ uid = CALL_UID,
+ )
+ )
+
+ assertThat(controller.hasOngoingCall()).isFalse()
+ }
+
+ @Test
+ fun hasOngoingCall_repoHasCallNotifThenDoesNot_returnsFalse() {
+ setCallNotifOnRepo()
+ setNoNotifsOnRepo()
+
+ assertThat(controller.hasOngoingCall()).isFalse()
+ }
+
+ @Test
+ fun hasOngoingCall_repoHasCallNotifThenScreeningNotif_returnsFalse() {
+ setCallNotifOnRepo()
+ setNotifOnRepo(
+ activeNotificationModel(
+ key = "screening",
+ callType = CallType.Screening,
+ uid = CALL_UID,
+ )
+ )
+
+ assertThat(controller.hasOngoingCall()).isFalse()
+ }
+
+ /**
+ * This test fakes a theme change during an ongoing call.
+ *
+ * When a theme change happens,
+ * [com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment] and its views get
+ * re-created, so [OngoingCallController.setChipView] gets called with a new view. If there's an
+ * active ongoing call when the theme changes, the new view needs to be updated with the call
+ * information.
+ */
+ @Test
+ fun setChipView_whenRepoHasOngoingCall_listenerNotifiedWithNewView() {
+ // Start an ongoing call.
+ setCallNotifOnRepo()
+ reset(mockOngoingCallListener)
+
+ lateinit var newChipView: View
+ TestableLooper.get(this).runWithLooper {
+ newChipView =
+ LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip, null)
+ }
+
+ // Change the chip view associated with the controller.
+ controller.setChipView(newChipView)
+
+ verify(mockOngoingCallListener).onOngoingCallStateChanged(any())
+ }
+
+ @Test
+ fun callProcessChangesToVisible_listenerNotified() {
+ // Start the call while the process is invisible.
+ whenever(mockIActivityManager.getUidProcessState(eq(CALL_UID), any()))
+ .thenReturn(PROC_STATE_INVISIBLE)
+ setCallNotifOnRepo()
+ reset(mockOngoingCallListener)
+
+ val captor = argumentCaptor<IUidObserver.Stub>()
+ verify(mockIActivityManager).registerUidObserver(captor.capture(), any(), any(), any())
+ val uidObserver = captor.firstValue
+
+ // Update the process to visible.
+ uidObserver.onUidStateChanged(CALL_UID, PROC_STATE_VISIBLE, 0, 0)
+ mainExecutor.advanceClockToLast()
+ mainExecutor.runAllReady()
+
+ verify(mockOngoingCallListener).onOngoingCallStateChanged(any())
+ }
+
+ @Test
+ fun callProcessChangesToInvisible_listenerNotified() {
+ // Start the call while the process is visible.
+ whenever(mockIActivityManager.getUidProcessState(eq(CALL_UID), any()))
+ .thenReturn(PROC_STATE_VISIBLE)
+ setCallNotifOnRepo()
+ reset(mockOngoingCallListener)
+
+ val captor = argumentCaptor<IUidObserver.Stub>()
+ verify(mockIActivityManager).registerUidObserver(captor.capture(), any(), any(), any())
+ val uidObserver = captor.firstValue
+
+ // Update the process to invisible.
+ uidObserver.onUidStateChanged(CALL_UID, PROC_STATE_INVISIBLE, 0, 0)
+ mainExecutor.advanceClockToLast()
+ mainExecutor.runAllReady()
+
+ verify(mockOngoingCallListener).onOngoingCallStateChanged(any())
+ }
+
+ /** Regression test for b/212467440. */
+ @Test
+ @DisableFlags(FLAG_STATUS_BAR_SCREEN_SHARING_CHIPS)
+ fun chipClicked_activityStarterTriggeredWithUnmodifiedIntent() {
+ val pendingIntent = mock<PendingIntent>()
+ setNotifOnRepo(
+ activeNotificationModel(
+ key = "notif",
+ uid = CALL_UID,
+ contentIntent = pendingIntent,
+ callType = CallType.Ongoing,
+ )
+ )
+
+ chipView.performClick()
+
+ // Ensure that the sysui didn't modify the notification's intent -- see b/212467440.
+ verify(mockActivityStarter).postStartActivityDismissingKeyguard(eq(pendingIntent), any())
+ }
+
+ @Test
+ @DisableFlags(FLAG_STATUS_BAR_SCREEN_SHARING_CHIPS)
+ fun callNotificationAdded_chipIsClickable() {
+ setCallNotifOnRepo()
+
+ assertThat(chipView.hasOnClickListeners()).isTrue()
+ }
+
+ @Test
+ @EnableFlags(FLAG_STATUS_BAR_SCREEN_SHARING_CHIPS)
+ fun callNotificationAdded_newChipsEnabled_chipNotClickable() {
+ setCallNotifOnRepo()
+
+ assertThat(chipView.hasOnClickListeners()).isFalse()
+ }
+
+ @Test
+ @DisableFlags(FLAG_STATUS_BAR_SCREEN_SHARING_CHIPS)
+ fun fullscreenIsTrue_chipStillClickable() {
+ setCallNotifOnRepo()
+ statusBarModeRepository.defaultDisplay.isInFullscreenMode.value = true
+ testScope.runCurrent()
+
+ assertThat(chipView.hasOnClickListeners()).isTrue()
+ }
+
+ @Test
+ fun callStartedInImmersiveMode_swipeGestureCallbackAdded() {
+ statusBarModeRepository.defaultDisplay.isInFullscreenMode.value = true
+ testScope.runCurrent()
+
+ setCallNotifOnRepo()
+
+ verify(mockSwipeStatusBarAwayGestureHandler).addOnGestureDetectedCallback(any(), any())
+ }
+
+ @Test
+ fun callStartedNotInImmersiveMode_swipeGestureCallbackNotAdded() {
+ statusBarModeRepository.defaultDisplay.isInFullscreenMode.value = false
+ testScope.runCurrent()
+
+ setCallNotifOnRepo()
+
+ verify(mockSwipeStatusBarAwayGestureHandler, never())
+ .addOnGestureDetectedCallback(any(), any())
+ }
+
+ @Test
+ fun transitionToImmersiveMode_swipeGestureCallbackAdded() {
+ setCallNotifOnRepo()
+
+ statusBarModeRepository.defaultDisplay.isInFullscreenMode.value = true
+ testScope.runCurrent()
+
+ verify(mockSwipeStatusBarAwayGestureHandler).addOnGestureDetectedCallback(any(), any())
+ }
+
+ @Test
+ fun transitionOutOfImmersiveMode_swipeGestureCallbackRemoved() {
+ statusBarModeRepository.defaultDisplay.isInFullscreenMode.value = true
+ testScope.runCurrent()
+
+ setCallNotifOnRepo()
+ reset(mockSwipeStatusBarAwayGestureHandler)
+
+ statusBarModeRepository.defaultDisplay.isInFullscreenMode.value = false
+ testScope.runCurrent()
+
+ verify(mockSwipeStatusBarAwayGestureHandler).removeOnGestureDetectedCallback(any())
+ }
+
+ @Test
+ fun callEndedWhileInImmersiveMode_swipeGestureCallbackRemoved() {
+ statusBarModeRepository.defaultDisplay.isInFullscreenMode.value = true
+ testScope.runCurrent()
+ setCallNotifOnRepo()
+ reset(mockSwipeStatusBarAwayGestureHandler)
+
+ setNoNotifsOnRepo()
+
+ verify(mockSwipeStatusBarAwayGestureHandler).removeOnGestureDetectedCallback(any())
+ }
+
+ private fun setCallNotifOnRepo() {
+ setNotifOnRepo(
+ activeNotificationModel(
+ key = "ongoingNotif",
+ callType = CallType.Ongoing,
+ uid = CALL_UID,
+ contentIntent = mock<PendingIntent>(),
+ )
+ )
+ }
+
+ private fun setNotifOnRepo(notif: ActiveNotificationModel) {
+ activeNotificationListRepository.activeNotifications.value =
+ ActiveNotificationsStore.Builder().apply { addIndividualNotif(notif) }.build()
+ testScope.runCurrent()
+ }
+
+ private fun setNoNotifsOnRepo() {
+ activeNotificationListRepository.activeNotifications.value =
+ ActiveNotificationsStore.Builder().build()
+ testScope.runCurrent()
+ }
+}
+
+private const val CALL_UID = 900
+
+// A process state that represents the process being visible to the user.
+private const val PROC_STATE_VISIBLE = ActivityManager.PROCESS_STATE_TOP
+
+// A process state that represents the process being invisible to the user.
+private const val PROC_STATE_INVISIBLE = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/data/repository/OngoingCallRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/data/repository/OngoingCallRepositoryTest.kt
index cbb8fe8..4c6eaa5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/data/repository/OngoingCallRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/data/repository/OngoingCallRepositoryTest.kt
@@ -21,6 +21,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel
+import com.android.systemui.statusbar.phone.ongoingcall.shared.model.inCallModel
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
@@ -33,7 +34,7 @@
@Test
fun hasOngoingCall_matchesSet() {
- val inCallModel = OngoingCallModel.InCall(startTimeMs = 654, intent = null)
+ val inCallModel = inCallModel(startTimeMs = 654)
underTest.setOngoingCallState(inCallModel)
assertThat(underTest.ongoingCallState.value).isEqualTo(inCallModel)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
index 9d83d5f..8fd0b31 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
@@ -59,7 +59,6 @@
import android.telephony.TelephonyManager.ERI_OFF
import android.telephony.TelephonyManager.ERI_ON
import android.telephony.TelephonyManager.EXTRA_CARRIER_ID
-import android.telephony.TelephonyManager.EXTRA_DATA_SPN
import android.telephony.TelephonyManager.EXTRA_PLMN
import android.telephony.TelephonyManager.EXTRA_SHOW_PLMN
import android.telephony.TelephonyManager.EXTRA_SHOW_SPN
@@ -86,6 +85,7 @@
import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest.Companion.configWithOverride
import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest.Companion.createTestConfig
+import com.android.systemui.statusbar.pipeline.mobile.data.model.toNetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.signalStrength
@@ -93,6 +93,8 @@
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.mockito.withArgCaptor
@@ -110,8 +112,6 @@
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
-import org.mockito.kotlin.any
-import org.mockito.kotlin.argumentCaptor
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
@OptIn(ExperimentalCoroutinesApi::class)
@@ -815,11 +815,9 @@
val intent = spnIntent()
val captor = argumentCaptor<BroadcastReceiver>()
verify(context).registerReceiver(captor.capture(), any())
- captor.lastValue.onReceive(context, intent)
+ captor.value!!.onReceive(context, intent)
- // spnIntent() sets all values to true and test strings
- assertThat(latest)
- .isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN$SEP$DATA_SPN"))
+ assertThat(latest).isEqualTo(intent.toNetworkNameModel(SEP))
job.cancel()
}
@@ -833,19 +831,17 @@
val intent = spnIntent()
val captor = argumentCaptor<BroadcastReceiver>()
verify(context).registerReceiver(captor.capture(), any())
- captor.lastValue.onReceive(context, intent)
+ captor.value!!.onReceive(context, intent)
- assertThat(latest)
- .isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN$SEP$DATA_SPN"))
+ assertThat(latest).isEqualTo(intent.toNetworkNameModel(SEP))
// WHEN an intent with a different subId is sent
val wrongSubIntent = spnIntent(subId = 101)
- captor.lastValue.onReceive(context, wrongSubIntent)
+ captor.value!!.onReceive(context, wrongSubIntent)
// THEN the previous intent's name is still used
- assertThat(latest)
- .isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN$SEP$DATA_SPN"))
+ assertThat(latest).isEqualTo(intent.toNetworkNameModel(SEP))
job.cancel()
}
@@ -859,10 +855,9 @@
val intent = spnIntent()
val captor = argumentCaptor<BroadcastReceiver>()
verify(context).registerReceiver(captor.capture(), any())
- captor.lastValue.onReceive(context, intent)
+ captor.value!!.onReceive(context, intent)
- assertThat(latest)
- .isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN$SEP$DATA_SPN"))
+ assertThat(latest).isEqualTo(intent.toNetworkNameModel(SEP))
val intentWithoutInfo =
spnIntent(
@@ -870,7 +865,7 @@
showPlmn = false,
)
- captor.lastValue.onReceive(context, intentWithoutInfo)
+ captor.value!!.onReceive(context, intentWithoutInfo)
assertThat(latest).isEqualTo(DEFAULT_NAME_MODEL)
@@ -889,88 +884,10 @@
val intent = spnIntent()
val captor = argumentCaptor<BroadcastReceiver>()
verify(context).registerReceiver(captor.capture(), any())
- captor.lastValue.onReceive(context, intent)
+ captor.value!!.onReceive(context, intent)
// The value is still there despite no active subscribers
- assertThat(underTest.networkName.value)
- .isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN$SEP$DATA_SPN"))
- }
-
- @Test
- fun networkName_allFieldsSet() =
- testScope.runTest {
- val latest by collectLastValue(underTest.networkName)
- val captor = argumentCaptor<BroadcastReceiver>()
- verify(context).registerReceiver(captor.capture(), any())
-
- val intent =
- spnIntent(
- subId = SUB_1_ID,
- showSpn = true,
- spn = SPN,
- dataSpn = null,
- showPlmn = true,
- plmn = PLMN,
- )
- captor.lastValue.onReceive(context, intent)
- assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
- }
-
- @Test
- fun networkName_showPlmn_plmnNotNull_showSpn_spnNull_dataSpnNotNull() =
- testScope.runTest {
- val latest by collectLastValue(underTest.networkName)
- val captor = argumentCaptor<BroadcastReceiver>()
- verify(context).registerReceiver(captor.capture(), any())
- val intent =
- spnIntent(
- subId = SUB_1_ID,
- showSpn = true,
- spn = null,
- dataSpn = DATA_SPN,
- showPlmn = true,
- plmn = PLMN,
- )
- captor.lastValue.onReceive(context, intent)
- assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
- }
-
- @Test
- fun networkName_showPlmn_noShowSPN() =
- testScope.runTest {
- val latest by collectLastValue(underTest.networkName)
- val captor = argumentCaptor<BroadcastReceiver>()
- verify(context).registerReceiver(captor.capture(), any())
- val intent =
- spnIntent(
- subId = SUB_1_ID,
- showSpn = false,
- spn = SPN,
- dataSpn = DATA_SPN,
- showPlmn = true,
- plmn = PLMN,
- )
- captor.lastValue.onReceive(context, intent)
- assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN"))
- }
-
- @Test
- fun networkName_showPlmn_plmnNull_showSpn() =
- testScope.runTest {
- val latest by collectLastValue(underTest.networkName)
- val captor = argumentCaptor<BroadcastReceiver>()
- verify(context).registerReceiver(captor.capture(), any())
- val intent =
- spnIntent(
- subId = SUB_1_ID,
- showSpn = true,
- spn = SPN,
- dataSpn = DATA_SPN,
- showPlmn = true,
- plmn = null,
- )
- captor.lastValue.onReceive(context, intent)
- assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$SPN$SEP$DATA_SPN"))
+ assertThat(underTest.networkName.value).isEqualTo(intent.toNetworkNameModel(SEP))
}
@Test
@@ -1211,16 +1128,14 @@
private fun spnIntent(
subId: Int = SUB_1_ID,
showSpn: Boolean = true,
- spn: String? = SPN,
- dataSpn: String? = DATA_SPN,
+ spn: String = SPN,
showPlmn: Boolean = true,
- plmn: String? = PLMN,
+ plmn: String = PLMN,
): Intent =
Intent(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED).apply {
putExtra(EXTRA_SUBSCRIPTION_INDEX, subId)
putExtra(EXTRA_SHOW_SPN, showSpn)
putExtra(EXTRA_SPN, spn)
- putExtra(EXTRA_DATA_SPN, dataSpn)
putExtra(EXTRA_SHOW_PLMN, showPlmn)
putExtra(EXTRA_PLMN, plmn)
}
@@ -1233,7 +1148,6 @@
private const val SEP = "-"
private const val SPN = "testSpn"
- private const val DATA_SPN = "testDataSpn"
private const val PLMN = "testPlmn"
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitorTest.kt
index 8875b84..9064f7c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitorTest.kt
@@ -17,20 +17,13 @@
package com.android.systemui.touchpad.tutorial.ui.gesture
import android.view.MotionEvent
-import android.view.MotionEvent.ACTION_DOWN
-import android.view.MotionEvent.ACTION_MOVE
-import android.view.MotionEvent.ACTION_POINTER_DOWN
-import android.view.MotionEvent.ACTION_POINTER_UP
-import android.view.MotionEvent.ACTION_UP
-import android.view.MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT
-import android.view.MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE
-import android.view.MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.FINISHED
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.IN_PROGRESS
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NOT_STARTED
+import com.android.systemui.touchpad.tutorial.ui.gesture.MultiFingerGesture.Companion.SWIPE_DISTANCE
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
@@ -46,135 +39,50 @@
gestureStateChangedCallback = { gestureState = it }
)
- companion object {
- const val SWIPE_DISTANCE = 100f
- }
-
@Test
fun triggersGestureFinishedForThreeFingerGestureRight() {
- val events =
- listOf(
- threeFingerEvent(ACTION_DOWN, x = 0f, y = 0f),
- threeFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f),
- threeFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f),
- threeFingerEvent(ACTION_MOVE, x = SWIPE_DISTANCE / 2, y = 0f),
- threeFingerEvent(ACTION_POINTER_UP, x = SWIPE_DISTANCE, y = 0f),
- threeFingerEvent(ACTION_POINTER_UP, x = SWIPE_DISTANCE, y = 0f),
- threeFingerEvent(ACTION_UP, x = SWIPE_DISTANCE, y = 0f),
- )
-
- events.forEach { gestureMonitor.processTouchpadEvent(it) }
-
- assertThat(gestureState).isEqualTo(FINISHED)
+ assertStateAfterEvents(events = ThreeFingerGesture.swipeRight(), expectedState = FINISHED)
}
@Test
fun triggersGestureFinishedForThreeFingerGestureLeft() {
- val events =
- listOf(
- threeFingerEvent(ACTION_DOWN, x = SWIPE_DISTANCE, y = 0f),
- threeFingerEvent(ACTION_POINTER_DOWN, x = SWIPE_DISTANCE, y = 0f),
- threeFingerEvent(ACTION_POINTER_DOWN, x = SWIPE_DISTANCE, y = 0f),
- threeFingerEvent(ACTION_MOVE, x = SWIPE_DISTANCE / 2, y = 0f),
- threeFingerEvent(ACTION_POINTER_UP, x = 0f, y = 0f),
- threeFingerEvent(ACTION_POINTER_UP, x = 0f, y = 0f),
- threeFingerEvent(ACTION_UP, x = 0f, y = 0f),
- )
-
- events.forEach { gestureMonitor.processTouchpadEvent(it) }
-
- assertThat(gestureState).isEqualTo(FINISHED)
+ assertStateAfterEvents(events = ThreeFingerGesture.swipeLeft(), expectedState = FINISHED)
}
@Test
fun triggersGestureProgressForThreeFingerGestureStarted() {
- val events =
- listOf(
- threeFingerEvent(ACTION_DOWN, x = SWIPE_DISTANCE, y = 0f),
- threeFingerEvent(ACTION_POINTER_DOWN, x = SWIPE_DISTANCE, y = 0f),
- threeFingerEvent(ACTION_POINTER_DOWN, x = SWIPE_DISTANCE, y = 0f),
- )
-
- events.forEach { gestureMonitor.processTouchpadEvent(it) }
-
- assertThat(gestureState).isEqualTo(IN_PROGRESS)
- }
-
- private fun threeFingerEvent(action: Int, x: Float, y: Float): MotionEvent {
- return motionEvent(
- action = action,
- x = x,
- y = y,
- classification = CLASSIFICATION_MULTI_FINGER_SWIPE,
- axisValues = mapOf(AXIS_GESTURE_SWIPE_FINGER_COUNT to 3f)
+ assertStateAfterEvents(
+ events = ThreeFingerGesture.startEvents(x = 0f, y = 0f),
+ expectedState = IN_PROGRESS
)
}
@Test
- fun doesntTriggerGestureFinished_onThreeFingersSwipeUp() {
- val events =
- listOf(
- threeFingerEvent(ACTION_DOWN, x = 0f, y = 0f),
- threeFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f),
- threeFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f),
- threeFingerEvent(ACTION_MOVE, x = 0f, y = SWIPE_DISTANCE / 2),
- threeFingerEvent(ACTION_POINTER_UP, x = 0f, y = SWIPE_DISTANCE),
- threeFingerEvent(ACTION_POINTER_UP, x = 0f, y = SWIPE_DISTANCE),
- threeFingerEvent(ACTION_UP, x = 0f, y = SWIPE_DISTANCE),
- )
+ fun doesntTriggerGestureFinished_onGestureDistanceTooShort() {
+ assertStateAfterEvents(
+ events = ThreeFingerGesture.swipeLeft(distancePx = SWIPE_DISTANCE / 2),
+ expectedState = NOT_STARTED
+ )
+ }
- events.forEach { gestureMonitor.processTouchpadEvent(it) }
-
- assertThat(gestureState).isEqualTo(NOT_STARTED)
+ @Test
+ fun doesntTriggerGestureFinished_onThreeFingersSwipeInOtherDirections() {
+ assertStateAfterEvents(events = ThreeFingerGesture.swipeUp(), expectedState = NOT_STARTED)
+ assertStateAfterEvents(events = ThreeFingerGesture.swipeDown(), expectedState = NOT_STARTED)
}
@Test
fun doesntTriggerGestureFinished_onTwoFingersSwipe() {
- fun twoFingerEvent(action: Int, x: Float, y: Float) =
- motionEvent(
- action = action,
- x = x,
- y = y,
- classification = CLASSIFICATION_TWO_FINGER_SWIPE,
- axisValues = mapOf(AXIS_GESTURE_SWIPE_FINGER_COUNT to 2f)
- )
- val events =
- listOf(
- twoFingerEvent(ACTION_DOWN, x = 0f, y = 0f),
- twoFingerEvent(ACTION_MOVE, x = SWIPE_DISTANCE / 2, y = 0f),
- twoFingerEvent(ACTION_UP, x = SWIPE_DISTANCE, y = 0f),
- )
-
- events.forEach { gestureMonitor.processTouchpadEvent(it) }
-
- assertThat(gestureState).isEqualTo(NOT_STARTED)
+ assertStateAfterEvents(events = TwoFingerGesture.swipeRight(), expectedState = NOT_STARTED)
}
@Test
fun doesntTriggerGestureFinished_onFourFingersSwipe() {
- fun fourFingerEvent(action: Int, x: Float, y: Float) =
- motionEvent(
- action = action,
- x = x,
- y = y,
- classification = CLASSIFICATION_MULTI_FINGER_SWIPE,
- axisValues = mapOf(AXIS_GESTURE_SWIPE_FINGER_COUNT to 4f)
- )
- val events =
- listOf(
- fourFingerEvent(ACTION_DOWN, x = 0f, y = 0f),
- fourFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f),
- fourFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f),
- fourFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f),
- fourFingerEvent(ACTION_MOVE, x = SWIPE_DISTANCE / 2, y = 0f),
- fourFingerEvent(ACTION_POINTER_UP, x = SWIPE_DISTANCE, y = 0f),
- fourFingerEvent(ACTION_POINTER_UP, x = SWIPE_DISTANCE, y = 0f),
- fourFingerEvent(ACTION_POINTER_UP, x = SWIPE_DISTANCE, y = 0f),
- fourFingerEvent(ACTION_UP, x = SWIPE_DISTANCE, y = 0f),
- )
+ assertStateAfterEvents(events = FourFingerGesture.swipeRight(), expectedState = NOT_STARTED)
+ }
+ private fun assertStateAfterEvents(events: List<MotionEvent>, expectedState: GestureState) {
events.forEach { gestureMonitor.processTouchpadEvent(it) }
-
- assertThat(gestureState).isEqualTo(NOT_STARTED)
+ assertThat(gestureState).isEqualTo(expectedState)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/HomeGestureMonitorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/HomeGestureMonitorTest.kt
new file mode 100644
index 0000000..6aefbe9
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/HomeGestureMonitorTest.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.touchpad.tutorial.ui.gesture
+
+import android.view.MotionEvent
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.FINISHED
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.IN_PROGRESS
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NOT_STARTED
+import com.android.systemui.touchpad.tutorial.ui.gesture.MultiFingerGesture.Companion.SWIPE_DISTANCE
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class HomeGestureMonitorTest : SysuiTestCase() {
+
+ private var gestureState = NOT_STARTED
+ private val gestureMonitor =
+ HomeGestureMonitor(
+ gestureDistanceThresholdPx = SWIPE_DISTANCE.toInt(),
+ gestureStateChangedCallback = { gestureState = it }
+ )
+
+ @Test
+ fun triggersGestureFinishedForThreeFingerGestureUp() {
+ assertStateAfterEvents(events = ThreeFingerGesture.swipeUp(), expectedState = FINISHED)
+ }
+
+ @Test
+ fun triggersGestureProgressForThreeFingerGestureStarted() {
+ assertStateAfterEvents(
+ events = ThreeFingerGesture.startEvents(x = 0f, y = 0f),
+ expectedState = IN_PROGRESS
+ )
+ }
+
+ @Test
+ fun doesntTriggerGestureFinished_onGestureDistanceTooShort() {
+ assertStateAfterEvents(
+ events = ThreeFingerGesture.swipeUp(distancePx = SWIPE_DISTANCE / 2),
+ expectedState = NOT_STARTED
+ )
+ }
+
+ @Test
+ fun doesntTriggerGestureFinished_onThreeFingersSwipeInOtherDirections() {
+ assertStateAfterEvents(events = ThreeFingerGesture.swipeDown(), expectedState = NOT_STARTED)
+ assertStateAfterEvents(events = ThreeFingerGesture.swipeLeft(), expectedState = NOT_STARTED)
+ assertStateAfterEvents(
+ events = ThreeFingerGesture.swipeRight(),
+ expectedState = NOT_STARTED
+ )
+ }
+
+ @Test
+ fun doesntTriggerGestureFinished_onTwoFingersSwipe() {
+ assertStateAfterEvents(events = TwoFingerGesture.swipeUp(), expectedState = NOT_STARTED)
+ }
+
+ @Test
+ fun doesntTriggerGestureFinished_onFourFingersSwipe() {
+ assertStateAfterEvents(events = FourFingerGesture.swipeUp(), expectedState = NOT_STARTED)
+ }
+
+ private fun assertStateAfterEvents(events: List<MotionEvent>, expectedState: GestureState) {
+ events.forEach { gestureMonitor.processTouchpadEvent(it) }
+ assertThat(gestureState).isEqualTo(expectedState)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureBuilder.kt b/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureBuilder.kt
new file mode 100644
index 0000000..296d4dc
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureBuilder.kt
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.touchpad.tutorial.ui.gesture
+
+import android.view.MotionEvent
+import android.view.MotionEvent.ACTION_DOWN
+import android.view.MotionEvent.ACTION_MOVE
+import android.view.MotionEvent.ACTION_POINTER_DOWN
+import android.view.MotionEvent.ACTION_POINTER_UP
+import android.view.MotionEvent.ACTION_UP
+import com.android.systemui.touchpad.tutorial.ui.gesture.MultiFingerGesture.Companion.DEFAULT_X
+import com.android.systemui.touchpad.tutorial.ui.gesture.MultiFingerGesture.Companion.DEFAULT_Y
+
+/**
+ * Interface for gesture builders which support creating list of [MotionEvent] for common swipe
+ * gestures. For simple usage see swipe* methods or use [createEvents] for more specific scenarios.
+ */
+interface MultiFingerGesture {
+
+ companion object {
+ const val SWIPE_DISTANCE = 100f
+ const val DEFAULT_X = 500f
+ const val DEFAULT_Y = 500f
+ }
+
+ fun swipeUp(distancePx: Float = SWIPE_DISTANCE) = createEvents { move(deltaY = -distancePx) }
+
+ fun swipeDown(distancePx: Float = SWIPE_DISTANCE) = createEvents { move(deltaY = distancePx) }
+
+ fun swipeRight(distancePx: Float = SWIPE_DISTANCE) = createEvents { move(deltaX = distancePx) }
+
+ fun swipeLeft(distancePx: Float = SWIPE_DISTANCE) = createEvents { move(deltaX = -distancePx) }
+
+ /**
+ * Creates gesture with provided move events. Note that move event's x and y is always relative
+ * to the starting one
+ */
+ fun createEvents(moveEvents: GestureBuilder.() -> Unit): List<MotionEvent>
+}
+
+object ThreeFingerGesture : MultiFingerGesture {
+ override fun createEvents(moveEvents: GestureBuilder.() -> Unit): List<MotionEvent> {
+ return touchpadGesture(
+ startEvents = { x, y -> startEvents(x, y) },
+ moveEvents = GestureBuilder(::threeFingerEvent).apply { moveEvents() }.events,
+ endEvents = { x, y -> endEvents(x, y) }
+ )
+ }
+
+ fun startEvents(x: Float, y: Float): List<MotionEvent> {
+ return listOf(
+ threeFingerEvent(ACTION_DOWN, x, y),
+ threeFingerEvent(ACTION_POINTER_DOWN, x, y),
+ threeFingerEvent(ACTION_POINTER_DOWN, x, y)
+ )
+ }
+
+ private fun endEvents(x: Float, y: Float): List<MotionEvent> {
+ return listOf(
+ threeFingerEvent(ACTION_POINTER_UP, x, y),
+ threeFingerEvent(ACTION_POINTER_UP, x, y),
+ threeFingerEvent(ACTION_UP, x, y)
+ )
+ }
+
+ private fun threeFingerEvent(
+ action: Int,
+ x: Float = DEFAULT_X,
+ y: Float = DEFAULT_Y
+ ): MotionEvent {
+ return touchpadEvent(
+ action = action,
+ x = x,
+ y = y,
+ classification = MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE,
+ axisValues = mapOf(MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT to 3f)
+ )
+ }
+}
+
+object FourFingerGesture : MultiFingerGesture {
+
+ override fun createEvents(moveEvents: GestureBuilder.() -> Unit): List<MotionEvent> {
+ return touchpadGesture(
+ startEvents = { x, y -> startEvents(x, y) },
+ moveEvents = GestureBuilder(::fourFingerEvent).apply { moveEvents() }.events,
+ endEvents = { x, y -> endEvents(x, y) }
+ )
+ }
+
+ private fun startEvents(x: Float, y: Float): List<MotionEvent> {
+ return listOf(
+ fourFingerEvent(ACTION_DOWN, x, y),
+ fourFingerEvent(ACTION_POINTER_DOWN, x, y),
+ fourFingerEvent(ACTION_POINTER_DOWN, x, y),
+ fourFingerEvent(ACTION_POINTER_DOWN, x, y)
+ )
+ }
+
+ private fun endEvents(x: Float, y: Float): List<MotionEvent> {
+ return listOf(
+ fourFingerEvent(ACTION_POINTER_UP, x, y),
+ fourFingerEvent(ACTION_POINTER_UP, x, y),
+ fourFingerEvent(ACTION_POINTER_UP, x, y),
+ fourFingerEvent(ACTION_UP, x, y)
+ )
+ }
+
+ private fun fourFingerEvent(
+ action: Int,
+ x: Float = DEFAULT_X,
+ y: Float = DEFAULT_Y
+ ): MotionEvent {
+ return touchpadEvent(
+ action = action,
+ x = x,
+ y = y,
+ classification = MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE,
+ axisValues = mapOf(MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT to 4f)
+ )
+ }
+}
+
+object TwoFingerGesture : MultiFingerGesture {
+
+ override fun createEvents(moveEvents: GestureBuilder.() -> Unit): List<MotionEvent> {
+ return touchpadGesture(
+ startEvents = { x, y -> listOf(twoFingerEvent(ACTION_DOWN, x, y)) },
+ moveEvents = GestureBuilder(::twoFingerEvent).apply { moveEvents() }.events,
+ endEvents = { x, y -> listOf(twoFingerEvent(ACTION_UP, x, y)) }
+ )
+ }
+
+ private fun twoFingerEvent(
+ action: Int,
+ x: Float = DEFAULT_X,
+ y: Float = DEFAULT_Y
+ ): MotionEvent {
+ return touchpadEvent(
+ action = action,
+ x = x,
+ y = y,
+ classification = MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE,
+ axisValues = mapOf(MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT to 2f)
+ )
+ }
+}
+
+private fun touchpadGesture(
+ startEvents: (Float, Float) -> List<MotionEvent>,
+ moveEvents: List<MotionEvent>,
+ endEvents: (Float, Float) -> List<MotionEvent>
+): List<MotionEvent> {
+ val lastX = moveEvents.last().x
+ val lastY = moveEvents.last().y
+ return startEvents(DEFAULT_X, DEFAULT_Y) + moveEvents + endEvents(lastX, lastY)
+}
+
+class GestureBuilder internal constructor(val eventBuilder: (Int, Float, Float) -> MotionEvent) {
+
+ val events = mutableListOf<MotionEvent>()
+
+ fun move(deltaX: Float = 0f, deltaY: Float = 0f) {
+ events.add(eventBuilder(ACTION_MOVE, DEFAULT_X + deltaX, DEFAULT_Y + deltaY))
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureBuilderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureBuilderTest.kt
new file mode 100644
index 0000000..13ebb42
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureBuilderTest.kt
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.touchpad.tutorial.ui.gesture
+
+import android.view.MotionEvent
+import android.view.MotionEvent.ACTION_DOWN
+import android.view.MotionEvent.ACTION_MOVE
+import android.view.MotionEvent.ACTION_POINTER_DOWN
+import android.view.MotionEvent.ACTION_POINTER_UP
+import android.view.MotionEvent.ACTION_UP
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.touchpad.tutorial.ui.gesture.MultiFingerGesture.Companion.DEFAULT_X
+import com.android.systemui.touchpad.tutorial.ui.gesture.MultiFingerGesture.Companion.DEFAULT_Y
+import com.google.common.truth.Truth.assertWithMessage
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class TouchpadGestureBuilderTest : SysuiTestCase() {
+
+ @Test
+ fun threeFingerSwipeProducesCorrectEvents() {
+ val events = ThreeFingerGesture.swipeRight()
+
+ events.forEach {
+ assertWithMessage("Event has three finger event parameters")
+ .that(isThreeFingerTouchpadSwipe(it))
+ .isTrue()
+ }
+ val actions = events.map { it.actionMasked }
+ assertWithMessage("Events have expected action type")
+ .that(actions)
+ .containsExactly(
+ ACTION_DOWN,
+ ACTION_POINTER_DOWN,
+ ACTION_POINTER_DOWN,
+ ACTION_MOVE,
+ ACTION_POINTER_UP,
+ ACTION_POINTER_UP,
+ ACTION_UP
+ )
+ .inOrder()
+ }
+
+ @Test
+ fun fourFingerSwipeProducesCorrectEvents() {
+ val events = FourFingerGesture.swipeUp()
+
+ events.forEach {
+ assertWithMessage("Event has four finger event parameters")
+ .that(isFourFingerTouchpadSwipe(it))
+ .isTrue()
+ }
+ val actions = events.map { it.actionMasked }
+ assertWithMessage("Events have expected action type")
+ .that(actions)
+ .containsExactly(
+ ACTION_DOWN,
+ ACTION_POINTER_DOWN,
+ ACTION_POINTER_DOWN,
+ ACTION_POINTER_DOWN,
+ ACTION_MOVE,
+ ACTION_POINTER_UP,
+ ACTION_POINTER_UP,
+ ACTION_POINTER_UP,
+ ACTION_UP
+ )
+ .inOrder()
+ }
+
+ @Test
+ fun twoFingerSwipeProducesCorrectEvents() {
+ val events = TwoFingerGesture.swipeLeft()
+
+ events.forEach {
+ assertWithMessage("Event has two finger event parameters")
+ .that(isTwoFingerGesture(it))
+ .isTrue()
+ }
+ val actions = events.map { it.actionMasked }
+ assertWithMessage("Events have expected action type")
+ .that(actions)
+ .containsExactlyElementsIn(listOf(ACTION_DOWN, ACTION_MOVE, ACTION_UP))
+ .inOrder()
+ }
+
+ private fun isTwoFingerGesture(event: MotionEvent): Boolean {
+ return event.classification == MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE &&
+ event.getAxisValue(MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT) == 2f
+ }
+
+ @Test
+ fun gestureBuilderProducesCorrectEventCoordinates() {
+ val events =
+ ThreeFingerGesture.createEvents {
+ move(deltaX = 50f)
+ move(deltaX = 100f)
+ }
+ val positions = events.map { it.x to it.y }
+ assertWithMessage("Events have expected coordinates")
+ .that(positions)
+ .containsExactly(
+ // down events
+ DEFAULT_X to DEFAULT_Y,
+ DEFAULT_X to DEFAULT_Y,
+ DEFAULT_X to DEFAULT_Y,
+ // move events
+ DEFAULT_X + 50f to DEFAULT_Y,
+ DEFAULT_X + 100f to DEFAULT_Y,
+ // up events
+ DEFAULT_X + 100f to DEFAULT_Y,
+ DEFAULT_X + 100f to DEFAULT_Y,
+ DEFAULT_X + 100f to DEFAULT_Y
+ )
+ .inOrder()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandlerTest.kt
index dc4d5f6..3a01d4f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandlerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandlerTest.kt
@@ -20,13 +20,6 @@
import android.view.InputDevice.SOURCE_TOUCHSCREEN
import android.view.MotionEvent
import android.view.MotionEvent.ACTION_DOWN
-import android.view.MotionEvent.ACTION_HOVER_ENTER
-import android.view.MotionEvent.ACTION_MOVE
-import android.view.MotionEvent.ACTION_POINTER_DOWN
-import android.view.MotionEvent.ACTION_POINTER_UP
-import android.view.MotionEvent.ACTION_UP
-import android.view.MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT
-import android.view.MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE
import android.view.MotionEvent.TOOL_TYPE_FINGER
import android.view.MotionEvent.TOOL_TYPE_MOUSE
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -34,7 +27,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.FINISHED
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NOT_STARTED
-import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGesture.BACK
+import com.android.systemui.touchpad.tutorial.ui.gesture.MultiFingerGesture.Companion.SWIPE_DISTANCE
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
@@ -44,11 +37,13 @@
class TouchpadGestureHandlerTest : SysuiTestCase() {
private var gestureState = NOT_STARTED
- private val handler = TouchpadGestureHandler(BACK, SWIPE_DISTANCE) { gestureState = it }
-
- companion object {
- const val SWIPE_DISTANCE = 100
- }
+ private val handler =
+ TouchpadGestureHandler(
+ BackGestureMonitor(
+ gestureDistanceThresholdPx = SWIPE_DISTANCE.toInt(),
+ gestureStateChangedCallback = { gestureState = it }
+ )
+ )
@Test
fun handlesEventsFromTouchpad() {
@@ -90,37 +85,10 @@
}
private fun backGestureEvents(): List<MotionEvent> {
- // list of motion events read from device while doing back gesture
- val y = 100f
- return listOf(
- touchpadEvent(ACTION_HOVER_ENTER, x = 759f, y = y, pointerCount = 1),
- threeFingerTouchpadEvent(ACTION_DOWN, x = 759f, y = y, pointerCount = 1),
- threeFingerTouchpadEvent(ACTION_POINTER_DOWN, x = 759f, y = y, pointerCount = 2),
- threeFingerTouchpadEvent(ACTION_POINTER_DOWN, x = 759f, y = y, pointerCount = 3),
- threeFingerTouchpadEvent(ACTION_MOVE, x = 767f, y = y, pointerCount = 3),
- threeFingerTouchpadEvent(ACTION_MOVE, x = 785f, y = y, pointerCount = 3),
- threeFingerTouchpadEvent(ACTION_MOVE, x = 814f, y = y, pointerCount = 3),
- threeFingerTouchpadEvent(ACTION_MOVE, x = 848f, y = y, pointerCount = 3),
- threeFingerTouchpadEvent(ACTION_MOVE, x = 943f, y = y, pointerCount = 3),
- threeFingerTouchpadEvent(ACTION_POINTER_UP, x = 943f, y = y, pointerCount = 3),
- threeFingerTouchpadEvent(ACTION_POINTER_UP, x = 943f, y = y, pointerCount = 2),
- threeFingerTouchpadEvent(ACTION_UP, x = 943f, y = y, pointerCount = 1)
- )
- }
-
- private fun threeFingerTouchpadEvent(
- action: Int,
- x: Float,
- y: Float,
- pointerCount: Int
- ): MotionEvent {
- return touchpadEvent(
- action = action,
- x = x,
- y = y,
- pointerCount = pointerCount,
- classification = CLASSIFICATION_MULTI_FINGER_SWIPE,
- axisValues = mapOf(AXIS_GESTURE_SWIPE_FINGER_COUNT to 3f)
- )
+ return ThreeFingerGesture.createEvents {
+ move(deltaX = SWIPE_DISTANCE / 4)
+ move(deltaX = SWIPE_DISTANCE / 2)
+ move(deltaX = SWIPE_DISTANCE)
+ }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/settings/UserSettingsProxyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/settings/UserSettingsProxyTest.kt
index ead9939..eaeece9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/settings/UserSettingsProxyTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/settings/UserSettingsProxyTest.kt
@@ -17,7 +17,6 @@
package com.android.systemui.util.settings
import android.content.ContentResolver
-import android.content.pm.UserInfo
import android.database.ContentObserver
import android.net.Uri
import android.os.Handler
@@ -28,8 +27,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.settings.FakeUserTracker
-import com.android.systemui.settings.UserTracker
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -52,29 +49,21 @@
@TestableLooper.RunWithLooper
class UserSettingsProxyTest : SysuiTestCase() {
- private var mUserTracker = FakeUserTracker()
+ private var userId = MAIN_USER_ID
private val testDispatcher = StandardTestDispatcher()
- private var mSettings: UserSettingsProxy = FakeUserSettingsProxy(mUserTracker, testDispatcher)
+ private var mSettings: UserSettingsProxy = FakeUserSettingsProxy({ userId }, testDispatcher)
private var mContentObserver = object : ContentObserver(Handler(Looper.getMainLooper())) {}
private lateinit var testScope: TestScope
@Before
fun setUp() {
- mUserTracker.set(
- listOf(UserInfo(MAIN_USER_ID, "main", UserInfo.FLAG_MAIN)),
- selectedUserIndex = 0
- )
testScope = TestScope(testDispatcher)
}
@Test
fun registerContentObserverForUser_inputString_success() =
testScope.runTest {
- mSettings.registerContentObserverForUserSync(
- TEST_SETTING,
- mContentObserver,
- mUserTracker.userId
- )
+ mSettings.registerContentObserverForUserSync(TEST_SETTING, mContentObserver, userId)
verify(mSettings.getContentResolver())
.registerContentObserver(
eq(TEST_SETTING_URI),
@@ -87,11 +76,7 @@
@Test
fun registerContentObserverForUserSuspend_inputString_success() =
testScope.runTest {
- mSettings.registerContentObserverForUser(
- TEST_SETTING,
- mContentObserver,
- mUserTracker.userId
- )
+ mSettings.registerContentObserverForUser(TEST_SETTING, mContentObserver, userId)
verify(mSettings.getContentResolver())
.registerContentObserver(
eq(TEST_SETTING_URI),
@@ -104,11 +89,7 @@
@Test
fun registerContentObserverForUserAsync_inputString_success() =
testScope.runTest {
- mSettings.registerContentObserverForUserAsync(
- TEST_SETTING,
- mContentObserver,
- mUserTracker.userId
- )
+ mSettings.registerContentObserverForUserAsync(TEST_SETTING, mContentObserver, userId)
testScope.advanceUntilIdle()
verify(mSettings.getContentResolver())
.registerContentObserver(
@@ -126,7 +107,7 @@
TEST_SETTING,
notifyForDescendants = true,
mContentObserver,
- mUserTracker.userId
+ userId
)
verify(mSettings.getContentResolver())
.registerContentObserver(
@@ -144,7 +125,7 @@
TEST_SETTING,
notifyForDescendants = true,
mContentObserver,
- mUserTracker.userId
+ userId
)
verify(mSettings.getContentResolver())
.registerContentObserver(
@@ -164,7 +145,7 @@
TEST_SETTING,
notifyForDescendants = true,
mContentObserver,
- mUserTracker.userId
+ userId
)
testScope.advanceUntilIdle()
verify(mSettings.getContentResolver())
@@ -179,11 +160,7 @@
@Test
fun registerContentObserverForUser_inputUri_success() =
testScope.runTest {
- mSettings.registerContentObserverForUserSync(
- TEST_SETTING_URI,
- mContentObserver,
- mUserTracker.userId
- )
+ mSettings.registerContentObserverForUserSync(TEST_SETTING_URI, mContentObserver, userId)
verify(mSettings.getContentResolver())
.registerContentObserver(
eq(TEST_SETTING_URI),
@@ -196,11 +173,7 @@
@Test
fun registerContentObserverForUserSuspend_inputUri_success() =
testScope.runTest {
- mSettings.registerContentObserverForUser(
- TEST_SETTING_URI,
- mContentObserver,
- mUserTracker.userId
- )
+ mSettings.registerContentObserverForUser(TEST_SETTING_URI, mContentObserver, userId)
verify(mSettings.getContentResolver())
.registerContentObserver(
eq(TEST_SETTING_URI),
@@ -216,7 +189,7 @@
mSettings.registerContentObserverForUserAsync(
TEST_SETTING_URI,
mContentObserver,
- mUserTracker.userId
+ userId
)
testScope.advanceUntilIdle()
@@ -239,7 +212,7 @@
mSettings.registerContentObserverForUserAsync(
TEST_SETTING_URI,
mContentObserver,
- mUserTracker.userId,
+ userId,
runnable
)
testScope.advanceUntilIdle()
@@ -253,7 +226,7 @@
TEST_SETTING_URI,
notifyForDescendants = true,
mContentObserver,
- mUserTracker.userId
+ userId
)
verify(mSettings.getContentResolver())
.registerContentObserver(
@@ -271,14 +244,12 @@
TEST_SETTING_URI,
notifyForDescendants = true,
mContentObserver,
- mUserTracker.userId
+ userId
)
verify(mSettings.getContentResolver())
.registerContentObserver(
eq(TEST_SETTING_URI),
- eq(
- true,
- ),
+ eq(true),
eq(mContentObserver),
eq(MAIN_USER_ID)
)
@@ -291,7 +262,7 @@
TEST_SETTING_URI,
notifyForDescendants = true,
mContentObserver,
- mUserTracker.userId
+ userId
)
testScope.advanceUntilIdle()
verify(mSettings.getContentResolver())
@@ -585,7 +556,7 @@
* This class uses a mock of [ContentResolver] to test the [ContentObserver] registration APIs.
*/
private class FakeUserSettingsProxy(
- override val userTracker: UserTracker,
+ override val currentUserProvider: SettingsProxy.CurrentUserIdProvider,
val testDispatcher: CoroutineDispatcher
) : UserSettingsProxy {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index 2457eb7..e5e04dc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -123,6 +123,7 @@
import com.android.systemui.shade.ShadeController;
import com.android.systemui.shade.ShadeWindowLogger;
import com.android.systemui.shade.domain.interactor.ShadeInteractor;
+import com.android.systemui.shade.ui.viewmodel.NotificationShadeWindowModel;
import com.android.systemui.shared.notifications.domain.interactor.NotificationSettingsInteractor;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.NotificationEntryHelper;
@@ -351,6 +352,7 @@
private final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this);
private ShadeInteractor mShadeInteractor;
+ private NotificationShadeWindowModel mNotificationShadeWindowModel;
private ShellTaskOrganizer mShellTaskOrganizer;
private TaskViewTransitions mTaskViewTransitions;
@@ -409,6 +411,7 @@
when(deviceEntryUdfpsInteractor.isUdfpsSupported()).thenReturn(MutableStateFlow(false));
mShadeInteractor = mKosmos.getShadeInteractor();
+ mNotificationShadeWindowModel = mKosmos.getNotificationShadeWindowModel();
mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(
mContext,
@@ -431,6 +434,7 @@
mShadeWindowLogger,
() -> mSelectedUserInteractor,
mUserTracker,
+ mNotificationShadeWindowModel,
mKosmos::getCommunalInteractor
);
mNotificationShadeWindowController.fetchWindowRootView();
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorKosmos.kt
index 9236bd2..63323b2 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorKosmos.kt
@@ -19,9 +19,10 @@
import com.android.keyguard.keyguardUpdateMonitor
import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository
-import com.android.systemui.deviceentry.domain.interactor.deviceEntryFingerprintAuthInteractor
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryBiometricsAllowedInteractor
import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
+import com.android.systemui.keyguard.data.repository.deviceEntryFaceAuthRepository
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.kosmos.Kosmos
@@ -42,7 +43,7 @@
biometricSettingsRepository = biometricSettingsRepository,
systemClock = systemClock,
keyguardUpdateMonitor = keyguardUpdateMonitor,
- deviceEntryFingerprintAuthInteractor = { deviceEntryFingerprintAuthInteractor },
+ deviceEntryBiometricsAllowedInteractor = { deviceEntryBiometricsAllowedInteractor },
keyguardInteractor = { keyguardInteractor },
keyguardTransitionInteractor = { keyguardTransitionInteractor },
scope = testScope.backgroundScope,
@@ -55,6 +56,7 @@
this.keyguardBouncerRepository.setPrimaryShow(false)
this.biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
this.biometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(true)
+ this.deviceEntryFaceAuthRepository.setLockedOut(false)
whenever(this.keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(false)
whenever(this.keyguardStateController.isUnlocked).thenReturn(false)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelKosmos.kt
index de5f0f3..e70631e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelKosmos.kt
@@ -22,8 +22,8 @@
import com.android.systemui.bouncer.domain.interactor.simBouncerInteractor
import com.android.systemui.bouncer.shared.flag.composeBouncerFlags
import com.android.systemui.deviceentry.domain.interactor.biometricMessageInteractor
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryBiometricsAllowedInteractor
import com.android.systemui.deviceentry.domain.interactor.deviceEntryFaceAuthInteractor
-import com.android.systemui.deviceentry.domain.interactor.deviceEntryFingerprintAuthInteractor
import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
@@ -45,7 +45,7 @@
biometricMessageInteractor = biometricMessageInteractor,
faceAuthInteractor = deviceEntryFaceAuthInteractor,
deviceUnlockedInteractor = deviceUnlockedInteractor,
- fingerprintInteractor = deviceEntryFingerprintAuthInteractor,
+ deviceEntryBiometricsAllowedInteractor = deviceEntryBiometricsAllowedInteractor,
flags = composeBouncerFlags,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricsAllowedInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricsAllowedInteractorKosmos.kt
new file mode 100644
index 0000000..4357289
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricsAllowedInteractorKosmos.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.deviceentry.domain.interactor
+
+import com.android.systemui.biometrics.data.repository.facePropertyRepository
+import com.android.systemui.kosmos.Kosmos
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.deviceEntryBiometricsAllowedInteractor by
+ Kosmos.Fixture {
+ DeviceEntryBiometricsAllowedInteractor(
+ deviceEntryFingerprintAuthInteractor = deviceEntryFingerprintAuthInteractor,
+ deviceEntryFaceAuthInteractor = deviceEntryFaceAuthInteractor,
+ biometricSettingsInteractor = deviceEntryBiometricSettingsInteractor,
+ facePropertyRepository = facePropertyRepository,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/education/data/repository/FakeContextualEducationRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/education/data/repository/FakeContextualEducationRepository.kt
index bade91a..3816e1b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/education/data/repository/FakeContextualEducationRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/education/data/repository/FakeContextualEducationRepository.kt
@@ -16,8 +16,8 @@
package com.android.systemui.education.data.repository
+import com.android.systemui.contextualeducation.GestureType
import com.android.systemui.education.data.model.GestureEduModel
-import com.android.systemui.shared.education.GestureType
import java.time.Clock
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt
index b5ea619..616f2b6 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt
@@ -283,7 +283,7 @@
)
}
- override fun updateTransition(
+ override suspend fun updateTransition(
transitionId: UUID,
@FloatRange(from = 0.0, to = 1.0) value: Float,
state: TransitionState
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt
index be8048e..9b7bca6 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt
@@ -27,8 +27,8 @@
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.bouncer.ui.BouncerView
import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryBiometricsAllowedInteractor
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFingerprintAuthInteractor
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -87,7 +87,7 @@
FakeBiometricSettingsRepository(),
FakeSystemClock(),
keyguardUpdateMonitor,
- { mock(DeviceEntryFingerprintAuthInteractor::class.java) },
+ { mock(DeviceEntryBiometricsAllowedInteractor::class.java) },
{ mock(KeyguardInteractor::class.java) },
{ mock(KeyguardTransitionInteractor::class.java) },
{ mock(SceneInteractor::class.java) },
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
index 8614fc9..e6bd24b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
@@ -59,6 +59,7 @@
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.shade.shadeController
+import com.android.systemui.shade.ui.viewmodel.notificationShadeWindowModel
import com.android.systemui.statusbar.chips.ui.viewmodel.ongoingActivityChipsViewModel
import com.android.systemui.statusbar.notification.domain.interactor.seenNotificationsInteractor
import com.android.systemui.statusbar.notification.stack.domain.interactor.headsUpNotificationInteractor
@@ -140,6 +141,7 @@
val shadeController by lazy { kosmos.shadeController }
val shadeRepository by lazy { kosmos.shadeRepository }
val shadeInteractor by lazy { kosmos.shadeInteractor }
+ val notificationShadeWindowModel by lazy { kosmos.notificationShadeWindowModel }
val wifiInteractor by lazy { kosmos.wifiInteractor }
val fakeWifiRepository by lazy { kosmos.fakeWifiRepository }
val volumeDialogInteractor by lazy { kosmos.volumeDialogInteractor }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/ActivatableExt.kt
similarity index 71%
rename from packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/ActivatableExt.kt
index 1f04a44..d265559 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/ActivatableExt.kt
@@ -14,12 +14,17 @@
* limitations under the License.
*/
-package com.android.systemui.activatable
+package com.android.systemui.lifecycle
+import kotlin.coroutines.CoroutineContext
+import kotlin.coroutines.EmptyCoroutineContext
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
/** Activates [activatable] for the duration of the test. */
-fun Activatable.activateIn(testScope: TestScope) {
- testScope.backgroundScope.launch { activate() }
+fun Activatable.activateIn(
+ testScope: TestScope,
+ context: CoroutineContext = EmptyCoroutineContext,
+) {
+ testScope.backgroundScope.launch(context) { activate() }
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeActivatable.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeActivatable.kt
new file mode 100644
index 0000000..e8b2dd2
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeActivatable.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.lifecycle
+
+import kotlinx.coroutines.awaitCancellation
+
+class FakeActivatable(
+ private val onActivation: () -> Unit = {},
+ private val onDeactivation: () -> Unit = {},
+) : SafeActivatable() {
+ var activationCount = 0
+ var cancellationCount = 0
+
+ override suspend fun onActivated() {
+ activationCount++
+ onActivation()
+ try {
+ awaitCancellation()
+ } finally {
+ cancellationCount++
+ onDeactivation()
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeSysUiViewModel.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeSysUiViewModel.kt
new file mode 100644
index 0000000..9a56f24
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeSysUiViewModel.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.lifecycle
+
+import kotlinx.coroutines.awaitCancellation
+
+class FakeSysUiViewModel(
+ private val onActivation: () -> Unit = {},
+ private val onDeactivation: () -> Unit = {},
+) : SysUiViewModel() {
+ var activationCount = 0
+ var cancellationCount = 0
+
+ override suspend fun onActivated() {
+ activationCount++
+ onActivation()
+ try {
+ awaitCancellation()
+ } finally {
+ cancellationCount++
+ onDeactivation()
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/startable/ShadeStartableKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/startable/ShadeStartableKosmos.kt
index 79b80bc..a1f157f1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/startable/ShadeStartableKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/startable/ShadeStartableKosmos.kt
@@ -17,6 +17,7 @@
package com.android.systemui.shade.domain.startable
import android.content.applicationContext
+import com.android.systemui.biometrics.domain.interactor.displayStateInteractor
import com.android.systemui.common.ui.data.repository.configurationRepository
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
@@ -28,6 +29,7 @@
import com.android.systemui.shade.domain.interactor.panelExpansionInteractor
import com.android.systemui.shade.transition.ScrimShadeTransitionController
import com.android.systemui.statusbar.notification.stack.notificationStackScrollLayoutController
+import com.android.systemui.statusbar.phone.scrimController
import com.android.systemui.statusbar.policy.splitShadeStateController
import com.android.systemui.statusbar.pulseExpansionHandler
import com.android.systemui.util.mockito.mock
@@ -48,6 +50,8 @@
panelExpansionInteractorProvider = { panelExpansionInteractor },
shadeExpansionStateManager = shadeExpansionStateManager,
pulseExpansionHandler = pulseExpansionHandler,
+ displayStateInteractor = displayStateInteractor,
nsslc = notificationStackScrollLayoutController,
+ scrimController = scrimController,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeWindowModelKosmos.kt
similarity index 65%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeWindowModelKosmos.kt
index 1f04a44..cd4fab8 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/activatable/ActivatableExt.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeWindowModelKosmos.kt
@@ -14,12 +14,10 @@
* limitations under the License.
*/
-package com.android.systemui.activatable
+package com.android.systemui.shade.ui.viewmodel
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.TestScope
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.kosmos.Kosmos
-/** Activates [activatable] for the duration of the test. */
-fun Activatable.activateIn(testScope: TestScope) {
- testScope.backgroundScope.launch { activate() }
-}
+val Kosmos.notificationShadeWindowModel: NotificationShadeWindowModel by
+ Kosmos.Fixture { NotificationShadeWindowModel(keyguardTransitionInteractor) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryKosmos.kt
index ecfc168..6373851 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryKosmos.kt
@@ -25,7 +25,7 @@
val Kosmos.notificationSettingsRepository by
Kosmos.Fixture {
NotificationSettingsRepository(
- scope = testScope.backgroundScope,
+ backgroundScope = testScope.backgroundScope,
backgroundDispatcher = testDispatcher,
secureSettingsRepository = secureSettingsRepository,
systemSettingsRepository = systemSettingsRepository,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/data/model/ActiveNotificationModelBuilder.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/data/model/ActiveNotificationModelBuilder.kt
index 9c5c486..76bdc0d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/data/model/ActiveNotificationModelBuilder.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/data/model/ActiveNotificationModelBuilder.kt
@@ -16,14 +16,18 @@
package com.android.systemui.statusbar.notification.data.model
+import android.app.PendingIntent
import android.graphics.drawable.Icon
+import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
+import com.android.systemui.statusbar.notification.shared.CallType
import com.android.systemui.statusbar.notification.stack.BUCKET_UNKNOWN
/** Simple ActiveNotificationModel builder for use in tests. */
fun activeNotificationModel(
key: String,
groupKey: String? = null,
+ whenTime: Long = 0L,
isAmbient: Boolean = false,
isRowDismissed: Boolean = false,
isSilent: Boolean = false,
@@ -33,15 +37,19 @@
aodIcon: Icon? = null,
shelfIcon: Icon? = null,
statusBarIcon: Icon? = null,
+ statusBarChipIcon: StatusBarIconView? = null,
uid: Int = 0,
instanceId: Int? = null,
isGroupSummary: Boolean = false,
packageName: String = "pkg",
+ contentIntent: PendingIntent? = null,
bucket: Int = BUCKET_UNKNOWN,
+ callType: CallType = CallType.None,
) =
ActiveNotificationModel(
key = key,
groupKey = groupKey,
+ whenTime = whenTime,
isAmbient = isAmbient,
isRowDismissed = isRowDismissed,
isSilent = isSilent,
@@ -51,9 +59,12 @@
aodIcon = aodIcon,
shelfIcon = shelfIcon,
statusBarIcon = statusBarIcon,
+ statusBarChipIconView = statusBarChipIcon,
uid = uid,
packageName = packageName,
+ contentIntent = contentIntent,
instanceId = instanceId,
isGroupSummary = isGroupSummary,
bucket = bucket,
+ callType = callType,
)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ongoingcall/shared/model/OngoingCallModelBuilder.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ongoingcall/shared/model/OngoingCallModelBuilder.kt
new file mode 100644
index 0000000..3963d7c
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ongoingcall/shared/model/OngoingCallModelBuilder.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone.ongoingcall.shared.model
+
+import android.app.PendingIntent
+import com.android.systemui.statusbar.StatusBarIconView
+
+/** Helper for building [OngoingCallModel.InCall] instances in tests. */
+fun inCallModel(
+ startTimeMs: Long,
+ notificationIcon: StatusBarIconView? = null,
+ intent: PendingIntent? = null
+) = OngoingCallModel.InCall(startTimeMs, notificationIcon, intent)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorKosmos.kt
index 78242b6..aef0828 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorKosmos.kt
@@ -18,10 +18,12 @@
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.shared.notifications.data.repository.notificationSettingsRepository
import com.android.systemui.statusbar.policy.data.repository.zenModeRepository
val Kosmos.zenModeInteractor by Fixture {
ZenModeInteractor(
- repository = zenModeRepository,
+ zenModeRepository = zenModeRepository,
+ notificationSettingsRepository = notificationSettingsRepository,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettings.java b/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettings.java
index 3f0318b..d117466 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettings.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettings.java
@@ -28,9 +28,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
-import com.android.systemui.settings.FakeUserTracker;
-import com.android.systemui.settings.UserTracker;
-
import kotlinx.coroutines.CoroutineDispatcher;
import java.util.ArrayList;
@@ -44,12 +41,13 @@
new HashMap<>();
private final Map<String, List<ContentObserver>> mContentObserversAllUsers = new HashMap<>();
private final CoroutineDispatcher mDispatcher;
- private final UserTracker mUserTracker;
public static final Uri CONTENT_URI = Uri.parse("content://settings/fake");
@UserIdInt
private int mUserId = UserHandle.USER_CURRENT;
+ private final CurrentUserIdProvider mCurrentUserProvider;
+
/**
* @deprecated Please use FakeSettings(testDispatcher) to provide the same dispatcher used
* by main test scope.
@@ -57,17 +55,17 @@
@Deprecated
public FakeSettings() {
mDispatcher = StandardTestDispatcher(/* scheduler = */ null, /* name = */ null);
- mUserTracker = new FakeUserTracker();
+ mCurrentUserProvider = () -> mUserId;
}
public FakeSettings(CoroutineDispatcher dispatcher) {
mDispatcher = dispatcher;
- mUserTracker = new FakeUserTracker();
+ mCurrentUserProvider = () -> mUserId;
}
- public FakeSettings(CoroutineDispatcher dispatcher, UserTracker userTracker) {
+ public FakeSettings(CoroutineDispatcher dispatcher, CurrentUserIdProvider currentUserProvider) {
mDispatcher = dispatcher;
- mUserTracker = userTracker;
+ mCurrentUserProvider = currentUserProvider;
}
@VisibleForTesting
@@ -93,8 +91,8 @@
@NonNull
@Override
- public UserTracker getUserTracker() {
- return mUserTracker;
+ public CurrentUserIdProvider getCurrentUserProvider() {
+ return mCurrentUserProvider;
}
@NonNull
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettingsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettingsKosmos.kt
index 55044bf..76ef202 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettingsKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettingsKosmos.kt
@@ -19,6 +19,8 @@
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.kosmos.testDispatcher
-import com.android.systemui.settings.fakeUserTracker
+import com.android.systemui.settings.userTracker
-val Kosmos.fakeSettings: FakeSettings by Fixture { FakeSettings(testDispatcher, fakeUserTracker) }
+val Kosmos.fakeSettings: FakeSettings by Fixture {
+ FakeSettings(testDispatcher) { userTracker.userId }
+}
diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
index cbbce1a..8663593 100644
--- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
+++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
@@ -120,6 +120,14 @@
static final String SYSTEM_GENERATION = "system_gen";
static final String LOCK_GENERATION = "lock_gen";
+ static final String DEVICE_CONFIG_WIDTH = "device_config_width";
+
+ static final String DEVICE_CONFIG_HEIGHT = "device_config_height";
+
+ static final String DEVICE_CONFIG_SECONDARY_WIDTH = "device_config_secondary_width";
+
+ static final String DEVICE_CONFIG_SECONDARY_HEIGHT = "device_config_secondary_height";
+
static final float DEFAULT_ACCEPTABLE_PARALLAX = 0.2f;
// If this file exists, it means we exceeded our quota last time
@@ -175,6 +183,16 @@
// disk churn.
final int lastSysGeneration = sharedPrefs.getInt(SYSTEM_GENERATION, /* defValue= */ -1);
final int lastLockGeneration = sharedPrefs.getInt(LOCK_GENERATION, /* defValue= */ -1);
+
+ final int deviceConfigWidth = sharedPrefs.getInt(
+ DEVICE_CONFIG_WIDTH, /* defValue= */ -1);
+ final int deviceConfigHeight = sharedPrefs.getInt(
+ DEVICE_CONFIG_HEIGHT, /* defValue= */ -1);
+ final int deviceConfigSecondaryWidth = sharedPrefs.getInt(
+ DEVICE_CONFIG_SECONDARY_WIDTH, /* defValue= */ -1);
+ final int deviceConfigSecondaryHeight = sharedPrefs.getInt(
+ DEVICE_CONFIG_SECONDARY_HEIGHT, /* defValue= */ -1);
+
final int sysGeneration = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
final int lockGeneration = mWallpaperManager.getWallpaperId(FLAG_LOCK);
final boolean sysChanged = (sysGeneration != lastSysGeneration);
@@ -195,7 +213,11 @@
backupWallpaperInfoFile(/* sysOrLockChanged= */ sysChanged || lockChanged, data);
backupSystemWallpaperFile(sharedPrefs, sysChanged, sysGeneration, data);
backupLockWallpaperFileIfItExists(sharedPrefs, lockChanged, lockGeneration, data);
- backupDeviceInfoFile(data);
+
+ final boolean isDeviceConfigChanged = isDeviceConfigChanged(deviceConfigWidth,
+ deviceConfigHeight, deviceConfigSecondaryWidth, deviceConfigSecondaryHeight);
+
+ backupDeviceInfoFile(sharedPrefs, isDeviceConfigChanged, data);
} catch (Exception e) {
Slog.e(TAG, "Unable to back up wallpaper", e);
mEventLogger.onBackupException(e);
@@ -209,50 +231,72 @@
}
}
+ private boolean isDeviceConfigChanged(int width, int height, int secondaryWidth,
+ int secondaryHeight) {
+ Point currentDimensions = getScreenDimensions();
+ Display smallerDisplay = getSmallerDisplayIfExists();
+ Point currentSecondaryDimensions = smallerDisplay != null ? getRealSize(smallerDisplay) :
+ new Point(0, 0);
+
+ return (currentDimensions.x != width
+ || currentDimensions.y != height
+ || currentSecondaryDimensions.x != secondaryWidth
+ || currentSecondaryDimensions.y != secondaryHeight);
+ }
+
/**
* This method backs up the device dimension information. The device data will always get
* overwritten when triggering a backup
*/
- private void backupDeviceInfoFile(FullBackupDataOutput data)
+ private void backupDeviceInfoFile(SharedPreferences sharedPrefs, boolean isDeviceConfigChanged,
+ FullBackupDataOutput data)
throws IOException {
final File deviceInfoStage = new File(getFilesDir(), WALLPAPER_BACKUP_DEVICE_INFO_STAGE);
- // save the dimensions of the device with xml formatting
- Point dimensions = getScreenDimensions();
- Display smallerDisplay = getSmallerDisplayIfExists();
- Point secondaryDimensions = smallerDisplay != null ? getRealSize(smallerDisplay) :
- new Point(0, 0);
+ if (isDeviceConfigChanged) {
+ // save the dimensions of the device with xml formatting
+ Point dimensions = getScreenDimensions();
+ Display smallerDisplay = getSmallerDisplayIfExists();
+ Point secondaryDimensions = smallerDisplay != null ? getRealSize(smallerDisplay) :
+ new Point(0, 0);
- deviceInfoStage.createNewFile();
- FileOutputStream fstream = new FileOutputStream(deviceInfoStage, false);
- TypedXmlSerializer out = Xml.resolveSerializer(fstream);
- out.startDocument(null, true);
- out.startTag(null, "dimensions");
+ deviceInfoStage.createNewFile();
+ FileOutputStream fstream = new FileOutputStream(deviceInfoStage, false);
+ TypedXmlSerializer out = Xml.resolveSerializer(fstream);
+ out.startDocument(null, true);
+ out.startTag(null, "dimensions");
- out.startTag(null, "width");
- out.text(String.valueOf(dimensions.x));
- out.endTag(null, "width");
+ out.startTag(null, "width");
+ out.text(String.valueOf(dimensions.x));
+ out.endTag(null, "width");
- out.startTag(null, "height");
- out.text(String.valueOf(dimensions.y));
- out.endTag(null, "height");
+ out.startTag(null, "height");
+ out.text(String.valueOf(dimensions.y));
+ out.endTag(null, "height");
- if (smallerDisplay != null) {
- out.startTag(null, "secondarywidth");
- out.text(String.valueOf(secondaryDimensions.x));
- out.endTag(null, "secondarywidth");
+ if (smallerDisplay != null) {
+ out.startTag(null, "secondarywidth");
+ out.text(String.valueOf(secondaryDimensions.x));
+ out.endTag(null, "secondarywidth");
- out.startTag(null, "secondaryheight");
- out.text(String.valueOf(secondaryDimensions.y));
- out.endTag(null, "secondaryheight");
+ out.startTag(null, "secondaryheight");
+ out.text(String.valueOf(secondaryDimensions.y));
+ out.endTag(null, "secondaryheight");
+ }
+
+ out.endTag(null, "dimensions");
+ out.endDocument();
+ fstream.flush();
+ FileUtils.sync(fstream);
+ fstream.close();
+
+ SharedPreferences.Editor editor = sharedPrefs.edit();
+ editor.putInt(DEVICE_CONFIG_WIDTH, dimensions.x);
+ editor.putInt(DEVICE_CONFIG_HEIGHT, dimensions.y);
+ editor.putInt(DEVICE_CONFIG_SECONDARY_WIDTH, secondaryDimensions.x);
+ editor.putInt(DEVICE_CONFIG_SECONDARY_HEIGHT, secondaryDimensions.y);
+ editor.apply();
}
-
- out.endTag(null, "dimensions");
- out.endDocument();
- fstream.flush();
- FileUtils.sync(fstream);
- fstream.close();
-
if (DEBUG) Slog.v(TAG, "Storing device dimension data");
backupFile(deviceInfoStage, data);
}
diff --git a/packages/overlays/HsumConfigOverlay/Android.bp b/packages/overlays/HsumConfigOverlay/Android.bp
new file mode 100644
index 0000000..050b1f0
--- /dev/null
+++ b/packages/overlays/HsumConfigOverlay/Android.bp
@@ -0,0 +1,16 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+runtime_resource_overlay {
+ name: "HsumConfigOverlay",
+ certificate: "platform",
+
+ product_specific: true,
+ sdk_version: "current",
+}
diff --git a/packages/overlays/HsumConfigOverlay/AndroidManifest.xml b/packages/overlays/HsumConfigOverlay/AndroidManifest.xml
new file mode 100644
index 0000000..cd7a879
--- /dev/null
+++ b/packages/overlays/HsumConfigOverlay/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.internal.overlay.hsumconfig"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <overlay android:targetPackage="android" android:priority="2" android:isStatic="true" />
+</manifest>
diff --git a/packages/overlays/HsumConfigOverlay/OWNERS b/packages/overlays/HsumConfigOverlay/OWNERS
new file mode 100644
index 0000000..79dd1c9
--- /dev/null
+++ b/packages/overlays/HsumConfigOverlay/OWNERS
@@ -0,0 +1,2 @@
+# People who can approve submission
+include platform/frameworks/base:/MULTIUSER_OWNERS
diff --git a/packages/overlays/HsumConfigOverlay/res/values/config.xml b/packages/overlays/HsumConfigOverlay/res/values/config.xml
new file mode 100644
index 0000000..7dbdfc7
--- /dev/null
+++ b/packages/overlays/HsumConfigOverlay/res/values/config.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!-- Default configuration for Headless System User Mode (HSUM) builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- Whether multiple admins are allowed on the device. If set to true, new users can be created
+ with admin privileges and admin privileges can be granted/revoked from existing users. -->
+ <bool name="config_enableMultipleAdmins">true</bool>
+
+ <!-- Whether the device will automatically (at first boot) have a designated main user and treat
+ it as a permanent admin.
+ Since the main user is a permanent admin user it can't be deleted or downgraded to
+ non-admin status.
+ This is generally only relevant on headless system user mode (HSUM) devices; on other
+ devices, the main user is the system user which is always a permanent admin anyway.
+ Note that HSUM devices without this enabled will not automatically have a main user. -->
+ <bool name="config_isMainUserPermanentAdmin">true</bool>
+
+ <!-- Maximum number of users we allow to be running at a time.
+ Note that this includes the headless system user. -->
+ <integer name="config_multiuserMaxRunningUsers">4</integer>
+
+</resources>
diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp
index 7c8fd42..2de3c5e 100644
--- a/ravenwood/Android.bp
+++ b/ravenwood/Android.bp
@@ -181,13 +181,13 @@
visibility: ["//visibility:public"],
}
-// Carefully compiles against only test_current to support tests that
+// Carefully compiles against only module_current to support tests that
// want to verify they're unbundled. The "impl" library above is what
// ships inside the Ravenwood environment to actually drive any API
// access to implementation details.
-// This library needs to be statically linked to mainline tests as well,
-// which need to be able to run on multiple API levels, so we can't use
-// test APIs in this module.
+// We can't use test_current here because this library needs to be statically
+// linked to mainline tests as well, which can't use test APIs because they
+// need to be able to run on multiple API levels.
java_library {
name: "ravenwood-junit",
srcs: [
diff --git a/ravenwood/runtime-common-src/com/android/ravenwood/common/JvmWorkaround.java b/ravenwood/runtime-common-src/com/android/ravenwood/common/JvmWorkaround.java
index ee28099..0238baa 100644
--- a/ravenwood/runtime-common-src/com/android/ravenwood/common/JvmWorkaround.java
+++ b/ravenwood/runtime-common-src/com/android/ravenwood/common/JvmWorkaround.java
@@ -16,6 +16,7 @@
package com.android.ravenwood.common;
import java.io.FileDescriptor;
+import java.io.IOException;
/**
* Collection of methods to workaround limitation in the hostside JVM.
@@ -44,6 +45,11 @@
public abstract int getFdInt(FileDescriptor fd);
/**
+ * Equivalent to Android's Os.close(fd).
+ */
+ public abstract void closeFd(FileDescriptor fd) throws IOException;
+
+ /**
* Placeholder implementation for the host side.
*
* Even on the host side, we don't want to throw just because the class is loaded,
@@ -64,5 +70,10 @@
public int getFdInt(FileDescriptor fd) {
throw calledOnHostside();
}
+
+ @Override
+ public void closeFd(FileDescriptor fd) {
+ throw calledOnHostside();
+ }
}
}
diff --git a/ravenwood/runtime-common-src/com/android/ravenwood/common/OpenJdkWorkaround.java b/ravenwood/runtime-common-src/com/android/ravenwood/common/OpenJdkWorkaround.java
index 9aedaab..a260147 100644
--- a/ravenwood/runtime-common-src/com/android/ravenwood/common/OpenJdkWorkaround.java
+++ b/ravenwood/runtime-common-src/com/android/ravenwood/common/OpenJdkWorkaround.java
@@ -16,6 +16,8 @@
package com.android.ravenwood.common;
import java.io.FileDescriptor;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
class OpenJdkWorkaround extends JvmWorkaround {
@Override
@@ -43,4 +45,19 @@
+ " perhaps JRE has changed?", e);
}
}
+
+ @Override
+ public void closeFd(FileDescriptor fd) throws IOException {
+ try {
+ final Object obj = Class.forName("jdk.internal.access.SharedSecrets").getMethod(
+ "getJavaIOFileDescriptorAccess").invoke(null);
+ Class.forName("jdk.internal.access.JavaIOFileDescriptorAccess").getMethod(
+ "close", FileDescriptor.class).invoke(obj, fd);
+ } catch (InvocationTargetException e) {
+ SneakyThrow.sneakyThrow(e.getTargetException());
+ } catch (ReflectiveOperationException e) {
+ throw new RuntimeException("Failed to interact with raw FileDescriptor internals;"
+ + " perhaps JRE has changed?", e);
+ }
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/common/OnTaskActionClickListener.kt b/ravenwood/runtime-common-src/com/android/ravenwood/common/SneakyThrow.java
similarity index 60%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/common/OnTaskActionClickListener.kt
rename to ravenwood/runtime-common-src/com/android/ravenwood/common/SneakyThrow.java
index 14b9e7f..0dbf7df 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/common/OnTaskActionClickListener.kt
+++ b/ravenwood/runtime-common-src/com/android/ravenwood/common/SneakyThrow.java
@@ -13,15 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.wm.shell.windowdecor.common
+package com.android.ravenwood.common;
-/** A callback to be invoked when a Task's window decor element is clicked. */
-fun interface OnTaskActionClickListener {
+public class SneakyThrow {
+
+ private SneakyThrow() {
+ }
+
/**
- * Called when a task's decor element has been clicked.
- *
- * @param taskId the id of the task.
- * @param tag a readable identifier for the element.
+ * Throw checked exceptions without the need to declare in method signature
*/
- fun onClick(taskId: Int, tag: String)
+ public static void sneakyThrow(Throwable t) {
+ SneakyThrow.<RuntimeException>sneakyThrow_(t);
+ }
+
+ private static <T extends Throwable> void sneakyThrow_(Throwable t) throws T {
+ throw (T) t;
+ }
}
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/ParcelFileDescriptor_host.java b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/ParcelFileDescriptor_host.java
index 1a15d7a..5a3589d 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/ParcelFileDescriptor_host.java
+++ b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/ParcelFileDescriptor_host.java
@@ -16,105 +16,16 @@
package com.android.platform.test.ravenwood.nativesubstitution;
-import static android.os.ParcelFileDescriptor.MODE_APPEND;
-import static android.os.ParcelFileDescriptor.MODE_CREATE;
-import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
-import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
-import static android.os.ParcelFileDescriptor.MODE_TRUNCATE;
-import static android.os.ParcelFileDescriptor.MODE_WORLD_READABLE;
-import static android.os.ParcelFileDescriptor.MODE_WORLD_WRITEABLE;
-import static android.os.ParcelFileDescriptor.MODE_WRITE_ONLY;
-
-import android.system.ErrnoException;
-import android.system.Os;
-import android.util.Log;
-
-import com.android.internal.annotations.GuardedBy;
import com.android.ravenwood.common.JvmWorkaround;
-import java.io.File;
import java.io.FileDescriptor;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.util.HashMap;
-import java.util.Map;
public class ParcelFileDescriptor_host {
- private static final String TAG = "ParcelFileDescriptor_host";
-
- /**
- * Since we don't have a great way to keep an unmanaged {@code FileDescriptor} reference
- * alive, we keep a strong reference to the {@code RandomAccessFile} we used to open it. This
- * gives us a way to look up the original parent object when closing later.
- */
- @GuardedBy("sActive")
- private static final Map<FileDescriptor, RandomAccessFile> sActive = new HashMap<>();
-
- public static void native_setFdInt$ravenwood(FileDescriptor fd, int fdInt) {
+ public static void setFdInt(FileDescriptor fd, int fdInt) {
JvmWorkaround.getInstance().setFdInt(fd, fdInt);
}
- public static int native_getFdInt$ravenwood(FileDescriptor fd) {
+ public static int getFdInt(FileDescriptor fd) {
return JvmWorkaround.getInstance().getFdInt(fd);
}
-
- public static FileDescriptor native_open$ravenwood(File file, int pfdMode) throws IOException {
- if ((pfdMode & MODE_CREATE) != 0 && !file.exists()) {
- throw new FileNotFoundException();
- }
-
- final String modeString;
- if ((pfdMode & MODE_READ_WRITE) == MODE_READ_WRITE) {
- modeString = "rw";
- } else if ((pfdMode & MODE_WRITE_ONLY) == MODE_WRITE_ONLY) {
- modeString = "rw";
- } else if ((pfdMode & MODE_READ_ONLY) == MODE_READ_ONLY) {
- modeString = "r";
- } else {
- throw new IllegalArgumentException();
- }
-
- final RandomAccessFile raf = new RandomAccessFile(file, modeString);
-
- // Now that we have a real file on disk, match requested flags
- if ((pfdMode & MODE_TRUNCATE) != 0) {
- raf.setLength(0);
- }
- if ((pfdMode & MODE_APPEND) != 0) {
- raf.seek(raf.length());
- }
- if ((pfdMode & MODE_WORLD_READABLE) != 0) {
- file.setReadable(true, false);
- }
- if ((pfdMode & MODE_WORLD_WRITEABLE) != 0) {
- file.setWritable(true, false);
- }
-
- final FileDescriptor fd = raf.getFD();
- synchronized (sActive) {
- sActive.put(fd, raf);
- }
- return fd;
- }
-
- public static void native_close$ravenwood(FileDescriptor fd) {
- final RandomAccessFile raf;
- synchronized (sActive) {
- raf = sActive.remove(fd);
- }
- int fdInt = JvmWorkaround.getInstance().getFdInt(fd);
- try {
- if (raf != null) {
- raf.close();
- } else {
- // This FD wasn't created by native_open$ravenwood().
- // The FD was passed to the PFD ctor. Just close it.
- Os.close(fd);
- }
- } catch (IOException | ErrnoException e) {
- Log.w(TAG, "Exception thrown while closing fd " + fdInt, e);
- }
- }
}
-;
\ No newline at end of file
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Parcel_host.java b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Parcel_host.java
index 2df93cd..cb00b3e 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Parcel_host.java
+++ b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Parcel_host.java
@@ -495,6 +495,7 @@
return null;
}
nativeReadInt(nativePtr);
+ nativeReadInt(nativePtr);
return fd;
}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java b/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java
index 825ab72..ecaa816 100644
--- a/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java
+++ b/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java
@@ -15,9 +15,11 @@
*/
package android.system;
+import com.android.ravenwood.common.JvmWorkaround;
import com.android.ravenwood.common.RavenwoodRuntimeNative;
import java.io.FileDescriptor;
+import java.io.IOException;
/**
* OS class replacement used on Ravenwood. For now, we just implement APIs as we need them...
@@ -56,6 +58,15 @@
/** Ravenwood version of the OS API. */
public static void close(FileDescriptor fd) throws ErrnoException {
- RavenwoodRuntimeNative.close(fd);
+ try {
+ JvmWorkaround.getInstance().closeFd(fd);
+ } catch (IOException e) {
+ // The only valid error on Linux that can happen is EIO
+ throw new ErrnoException("close", OsConstants.EIO);
+ }
+ }
+
+ public static FileDescriptor open(String path, int flags, int mode) throws ErrnoException {
+ return RavenwoodRuntimeNative.open(path, flags, mode);
}
}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/common/RavenwoodRuntimeNative.java b/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/common/RavenwoodRuntimeNative.java
index 2bc8e71..beba833 100644
--- a/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/common/RavenwoodRuntimeNative.java
+++ b/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/common/RavenwoodRuntimeNative.java
@@ -48,7 +48,7 @@
public static native StructStat stat(String path) throws ErrnoException;
- private static native void nClose(int fd) throws ErrnoException;
+ private static native int nOpen(String path, int flags, int mode) throws ErrnoException;
public static long lseek(FileDescriptor fd, long offset, int whence) throws ErrnoException {
return nLseek(JvmWorkaround.getInstance().getFdInt(fd), offset, whence);
@@ -69,7 +69,7 @@
public static FileDescriptor dup(FileDescriptor fd) throws ErrnoException {
var fdInt = nDup(JvmWorkaround.getInstance().getFdInt(fd));
- var retFd = new java.io.FileDescriptor();
+ var retFd = new FileDescriptor();
JvmWorkaround.getInstance().setFdInt(retFd, fdInt);
return retFd;
}
@@ -86,10 +86,11 @@
return nFstat(fdInt);
}
- /** See close(2) */
- public static void close(FileDescriptor fd) throws ErrnoException {
- var fdInt = JvmWorkaround.getInstance().getFdInt(fd);
-
- nClose(fdInt);
+ public static FileDescriptor open(String path, int flags, int mode) throws ErrnoException {
+ int fd = nOpen(path, flags, mode);
+ if (fd < 0) return null;
+ var retFd = new FileDescriptor();
+ JvmWorkaround.getInstance().setFdInt(retFd, fd);
+ return retFd;
}
}
diff --git a/ravenwood/runtime-jni/ravenwood_runtime.cpp b/ravenwood/runtime-jni/ravenwood_runtime.cpp
index ee84954..c804928 100644
--- a/ravenwood/runtime-jni/ravenwood_runtime.cpp
+++ b/ravenwood/runtime-jni/ravenwood_runtime.cpp
@@ -18,9 +18,11 @@
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>
+#include <string>
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedLocalRef.h>
#include <nativehelper/ScopedUtfChars.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
#include "jni.h"
#include "utils/Log.h"
@@ -49,6 +51,43 @@
static jclass g_StructStat;
static jclass g_StructTimespecClass;
+// We have to explicitly decode the string to real UTF-8, because when using GetStringUTFChars
+// we only get modified UTF-8, which is not the platform string type used in host JVM.
+struct ScopedRealUtf8Chars {
+ ScopedRealUtf8Chars(JNIEnv* env, jstring s) : valid_(false) {
+ if (s == nullptr) {
+ jniThrowNullPointerException(env);
+ return;
+ }
+ jclass clazz = env->GetObjectClass(s);
+ jmethodID getBytes = env->GetMethodID(clazz, "getBytes", "(Ljava/lang/String;)[B");
+
+ ScopedLocalRef<jstring> utf8(env, env->NewStringUTF("UTF-8"));
+ ScopedLocalRef<jbyteArray> jbytes(env,
+ (jbyteArray) env->CallObjectMethod(s, getBytes, utf8.get()));
+
+ ScopedByteArrayRO bytes(env, jbytes.get());
+ string_.append((const char *) bytes.get(), bytes.size());
+ valid_ = true;
+ }
+
+ const char* c_str() const {
+ return valid_ ? string_.c_str() : nullptr;
+ }
+
+ size_t size() const {
+ return string_.size();
+ }
+
+ const char& operator[](size_t n) const {
+ return string_[n];
+ }
+
+private:
+ std::string string_;
+ bool valid_;
+};
+
static jclass findClass(JNIEnv* env, const char* name) {
ScopedLocalRef<jclass> localClass(env, env->FindClass(name));
jclass result = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get()));
@@ -99,7 +138,7 @@
}
static jobject doStat(JNIEnv* env, jstring javaPath, bool isLstat) {
- ScopedUtfChars path(env, javaPath);
+ ScopedRealUtf8Chars path(env, javaPath);
if (path.c_str() == NULL) {
return NULL;
}
@@ -167,9 +206,12 @@
return doStat(env, javaPath, false);
}
-static void nClose(JNIEnv* env, jclass, jint fd) {
- // Don't use TEMP_FAILURE_RETRY() on close(): https://lkml.org/lkml/2005/9/10/129
- throwIfMinusOne(env, "close", close(fd));
+static jint Linux_open(JNIEnv* env, jobject, jstring javaPath, jint flags, jint mode) {
+ ScopedRealUtf8Chars path(env, javaPath);
+ if (path.c_str() == NULL) {
+ return -1;
+ }
+ return throwIfMinusOne(env, "open", TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode)));
}
// ---- Registration ----
@@ -184,7 +226,7 @@
{ "nFstat", "(I)Landroid/system/StructStat;", (void*)nFstat },
{ "lstat", "(Ljava/lang/String;)Landroid/system/StructStat;", (void*)Linux_lstat },
{ "stat", "(Ljava/lang/String;)Landroid/system/StructStat;", (void*)Linux_stat },
- { "nClose", "(I)V", (void*)nClose },
+ { "nOpen", "(Ljava/lang/String;II)I", (void*)Linux_open },
};
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
diff --git a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
index bdc3577..68f185e 100644
--- a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
+++ b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
@@ -143,6 +143,7 @@
android.os.HandlerExecutor
android.os.HandlerThread
android.os.IBinder
+android.os.LocaleList
android.os.Looper
android.os.Message
android.os.MessageQueue
diff --git a/services/Android.bp b/services/Android.bp
index dce6aa7..ded7379 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -108,6 +108,8 @@
filegroup {
name: "services-non-updatable-sources",
srcs: [
+ ":incremental_aidl",
+ ":services.core-aidl-sources",
":services.core-sources",
":services.core-sources-am-wm",
"core/java/com/android/server/am/package.html",
@@ -377,4 +379,8 @@
},
},
api_surface: "system-server",
+ sdk_version: "module_current",
+ libs: [
+ "framework-annotations-lib",
+ ],
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 099cb28..d16a665 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -45,9 +45,11 @@
import com.android.server.LocalServices;
import com.android.server.accessibility.gestures.TouchExplorer;
+import com.android.server.accessibility.magnification.FullScreenMagnificationController;
import com.android.server.accessibility.magnification.FullScreenMagnificationGestureHandler;
import com.android.server.accessibility.magnification.FullScreenMagnificationVibrationHelper;
import com.android.server.accessibility.magnification.MagnificationGestureHandler;
+import com.android.server.accessibility.magnification.MouseEventHandler;
import com.android.server.accessibility.magnification.WindowMagnificationGestureHandler;
import com.android.server.accessibility.magnification.WindowMagnificationPromptController;
import com.android.server.policy.WindowManagerPolicy;
@@ -864,15 +866,21 @@
TYPE_MAGNIFICATION_OVERLAY, null /* options */);
FullScreenMagnificationVibrationHelper fullScreenMagnificationVibrationHelper =
new FullScreenMagnificationVibrationHelper(uiContext);
- magnificationGestureHandler = new FullScreenMagnificationGestureHandler(uiContext,
- mAms.getMagnificationController().getFullScreenMagnificationController(),
- mAms.getTraceManager(),
- mAms.getMagnificationController(),
- detectControlGestures,
- detectTwoFingerTripleTap,
- triggerable,
- new WindowMagnificationPromptController(displayContext, mUserId), displayId,
- fullScreenMagnificationVibrationHelper);
+ FullScreenMagnificationController controller =
+ mAms.getMagnificationController().getFullScreenMagnificationController();
+ magnificationGestureHandler =
+ new FullScreenMagnificationGestureHandler(
+ uiContext,
+ controller,
+ mAms.getTraceManager(),
+ mAms.getMagnificationController(),
+ detectControlGestures,
+ detectTwoFingerTripleTap,
+ triggerable,
+ new WindowMagnificationPromptController(displayContext, mUserId),
+ displayId,
+ fullScreenMagnificationVibrationHelper,
+ new MouseEventHandler(controller));
}
return magnificationGestureHandler;
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 9067cda..45fcf6b 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -4090,11 +4090,7 @@
boolean enable, @UserShortcutType int shortcutTypes,
@NonNull List<String> shortcutTargets, @UserIdInt int userId) {
enableShortcutsForTargets_enforcePermission();
- if ((shortcutTypes & GESTURE) == GESTURE
- && !android.provider.Flags.a11yStandaloneGestureEnabled()) {
- throw new IllegalArgumentException(
- "GESTURE type shortcuts are disabled by feature flag");
- }
+
for (int shortcutType : USER_SHORTCUT_TYPES) {
if ((shortcutTypes & shortcutType) == shortcutType) {
enableShortcutForTargets(enable, shortcutType, shortcutTargets, userId);
@@ -4105,6 +4101,13 @@
private void enableShortcutForTargets(
boolean enable, @UserShortcutType int shortcutType,
@NonNull List<String> shortcutTargets, @UserIdInt int userId) {
+ if (shortcutType == UserShortcutType.GESTURE
+ && !android.provider.Flags.a11yStandaloneGestureEnabled()) {
+ Slog.w(LOG_TAG,
+ "GESTURE type shortcuts are disabled by feature flag");
+ return;
+ }
+
final String shortcutTypeSettingKey = ShortcutUtils.convertToKey(shortcutType);
if (shortcutType == UserShortcutType.TRIPLETAP
|| shortcutType == UserShortcutType.TWOFINGER_DOUBLETAP) {
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/MultiTap.java b/services/accessibility/java/com/android/server/accessibility/gestures/MultiTap.java
index af5433e..95559802 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/MultiTap.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/MultiTap.java
@@ -43,12 +43,18 @@
public MultiTap(Context context, int taps, int gesture,
GestureMatcher.StateChangeListener listener) {
+ this(context, taps, gesture,
+ ViewConfiguration.getDoubleTapTimeout(), listener);
+ }
+
+ public MultiTap(Context context, int taps, int gesture, int multiTapTimeout,
+ GestureMatcher.StateChangeListener listener) {
super(gesture, new Handler(context.getMainLooper()), listener);
mTargetTaps = taps;
+ mDoubleTapTimeout = multiTapTimeout;
mDoubleTapSlop = ViewConfiguration.get(context).getScaledDoubleTapSlop();
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mTapTimeout = ViewConfiguration.getTapTimeout();
- mDoubleTapTimeout = ViewConfiguration.getDoubleTapTimeout();
clear();
}
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/MultiTapAndHold.java b/services/accessibility/java/com/android/server/accessibility/gestures/MultiTapAndHold.java
index 8363eca..15e1278 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/MultiTapAndHold.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/MultiTapAndHold.java
@@ -30,6 +30,11 @@
super(context, taps, gesture, listener);
}
+ public MultiTapAndHold(Context context, int taps, int gesture, int multiTapTimeout,
+ GestureMatcher.StateChangeListener listener) {
+ super(context, taps, gesture, multiTapTimeout, listener);
+ }
+
@Override
protected void onDown(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
super.onDown(event, rawEvent, policyFlags);
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
index b5b998f..6b6b39d 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
@@ -1131,7 +1131,10 @@
}
if (isAlwaysOnMagnificationEnabled()) {
- zoomOutFromService(displayId);
+ if (!mControllerCtx.getContext().getResources().getBoolean(
+ R.bool.config_magnification_keep_zoom_level_when_context_changed)) {
+ zoomOutFromService(displayId);
+ }
} else {
reset(displayId, true);
}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
index 0ee5896..b052d23 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
@@ -16,6 +16,8 @@
package com.android.server.accessibility.magnification;
+import static android.view.InputDevice.SOURCE_MOUSE;
+import static android.view.InputDevice.SOURCE_STYLUS;
import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
@@ -183,7 +185,10 @@
private final int mMinimumVelocity;
private final int mMaximumVelocity;
- public FullScreenMagnificationGestureHandler(@UiContext Context context,
+ private MouseEventHandler mMouseEventHandler;
+
+ public FullScreenMagnificationGestureHandler(
+ @UiContext Context context,
FullScreenMagnificationController fullScreenMagnificationController,
AccessibilityTraceManager trace,
Callback callback,
@@ -192,7 +197,8 @@
boolean detectShortcutTrigger,
@NonNull WindowMagnificationPromptController promptController,
int displayId,
- FullScreenMagnificationVibrationHelper fullScreenMagnificationVibrationHelper) {
+ FullScreenMagnificationVibrationHelper fullScreenMagnificationVibrationHelper,
+ MouseEventHandler mouseEventHandler) {
this(
context,
fullScreenMagnificationController,
@@ -207,9 +213,8 @@
/* magnificationLogger= */ null,
ViewConfiguration.get(context),
new OneFingerPanningSettingsProvider(
- context,
- Flags.enableMagnificationOneFingerPanningGesture()
- ));
+ context, Flags.enableMagnificationOneFingerPanningGesture()),
+ mouseEventHandler);
}
/** Constructor for tests. */
@@ -227,8 +232,8 @@
FullScreenMagnificationVibrationHelper fullScreenMagnificationVibrationHelper,
MagnificationLogger magnificationLogger,
ViewConfiguration viewConfiguration,
- OneFingerPanningSettingsProvider oneFingerPanningSettingsProvider
- ) {
+ OneFingerPanningSettingsProvider oneFingerPanningSettingsProvider,
+ MouseEventHandler mouseEventHandler) {
super(displayId, detectSingleFingerTripleTap, detectTwoFingerTripleTap,
detectShortcutTrigger, trace, callback);
if (DEBUG_ALL) {
@@ -318,6 +323,7 @@
mOverscrollEdgeSlop = context.getResources().getDimensionPixelSize(
R.dimen.accessibility_fullscreen_magnification_gesture_edge_slop);
mIsWatch = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
+ mMouseEventHandler = mouseEventHandler;
if (mDetectShortcutTrigger) {
mScreenStateReceiver = new ScreenStateReceiver(context, this);
@@ -331,15 +337,28 @@
@Override
void onMotionEventInternal(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
- if (event.getActionMasked() == ACTION_DOWN) {
- cancelFling();
- }
+ if (event.getSource() == SOURCE_TOUCHSCREEN) {
+ if (event.getActionMasked() == ACTION_DOWN) {
+ cancelFling();
+ }
+ handleTouchEventWith(mCurrentState, event, rawEvent, policyFlags);
+ } else if (Flags.enableMagnificationFollowsMouse()
+ && (event.getSource() == SOURCE_MOUSE || event.getSource() == SOURCE_STYLUS)) {
+ if (mFullScreenMagnificationController.isActivated(mDisplayId)) {
+ // TODO(b/354696546): Allow mouse/stylus to activate whichever display they are
+ // over, rather than only interacting with the current display.
- handleEventWith(mCurrentState, event, rawEvent, policyFlags);
+ // Send through the mouse/stylus event handler.
+ mMouseEventHandler.onEvent(event, mDisplayId);
+ }
+ // Dispatch to normal event handling flow.
+ dispatchTransformedEvent(event, rawEvent, policyFlags);
+ }
}
- private void handleEventWith(State stateHandler,
- MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ private void handleTouchEventWith(
+ State stateHandler, MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+
// To keep InputEventConsistencyVerifiers within GestureDetectors happy
mPanningScalingState.mScrollGestureDetector.onTouchEvent(event);
mPanningScalingState.mScaleGestureDetector.onTouchEvent(event);
@@ -1168,9 +1187,8 @@
DetectingState(Context context) {
mLongTapMinDelay = ViewConfiguration.getLongPressTimeout();
- mMultiTapMaxDelay = ViewConfiguration.getDoubleTapTimeout()
- + context.getResources().getInteger(
- R.integer.config_screen_magnification_multi_tap_adjustment);
+ mMultiTapMaxDelay =
+ MagnificationGestureMatcher.getMagnificationMultiTapTimeout(context);
mSwipeMinDistance = ViewConfiguration.get(context).getScaledTouchSlop();
mMultiTapMaxDistance = ViewConfiguration.get(context).getScaledDoubleTapSlop();
}
@@ -1422,6 +1440,11 @@
protected void cacheDelayedMotionEvent(MotionEvent event, MotionEvent rawEvent,
int policyFlags) {
+ if (Flags.enableMagnificationFollowsMouse()
+ && !event.isFromSource(SOURCE_TOUCHSCREEN)) {
+ // Only touch events need to be cached and sent later.
+ return;
+ }
if (event.getActionMasked() == ACTION_DOWN) {
mPreLastDown = mLastDown;
mLastDown = MotionEvent.obtain(event);
@@ -1459,7 +1482,7 @@
mDelayedEventQueue = info.mNext;
info.event.setDownTime(info.event.getDownTime() + offset);
- handleEventWith(mDelegatingState, info.event, info.rawEvent, info.policyFlags);
+ handleTouchEventWith(mDelegatingState, info.event, info.rawEvent, info.policyFlags);
info.recycle();
} while (mDelayedEventQueue != null);
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGestureHandler.java
index 11d0713..08411c2 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGestureHandler.java
@@ -16,6 +16,8 @@
package com.android.server.accessibility.magnification;
+import static android.view.InputDevice.SOURCE_MOUSE;
+import static android.view.InputDevice.SOURCE_STYLUS;
import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_UP;
@@ -139,12 +141,35 @@
}
}
+ /**
+ * Some touchscreen, mouse and stylus events may modify magnifier state. Checks for whether the
+ * event should not be dispatched to the magnifier.
+ *
+ * @param event The event to check.
+ * @return `true` if the event should be sent through the normal event flow or `false` if it
+ * should be observed by magnifier.
+ */
private boolean shouldDispatchTransformedEvent(MotionEvent event) {
- if ((!mDetectSingleFingerTripleTap && !mDetectTwoFingerTripleTap && !mDetectShortcutTrigger)
- || !event.isFromSource(SOURCE_TOUCHSCREEN)) {
- return true;
+ if (event.getSource() == SOURCE_TOUCHSCREEN) {
+ if (mDetectSingleFingerTripleTap
+ || mDetectTwoFingerTripleTap
+ || mDetectShortcutTrigger) {
+ // Observe touchscreen events while magnification activation is detected.
+ return false;
+ }
}
- return false;
+ if (Flags.enableMagnificationFollowsMouse()) {
+ if (event.isFromSource(SOURCE_MOUSE) || event.isFromSource(SOURCE_STYLUS)) {
+ // Note that mouse events include other mouse-like pointing devices
+ // such as touchpads and pointing sticks.
+ // Observe any mouse or stylus movement.
+ // We observe all movement to ensure that events continue to come in order,
+ // even though only some movement types actually move the viewport.
+ return false;
+ }
+ }
+ // Magnification dispatches (ignores) all other events
+ return true;
}
final void dispatchTransformedEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MouseEventHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/MouseEventHandler.java
new file mode 100644
index 0000000..845249e
--- /dev/null
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MouseEventHandler.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.accessibility.magnification;
+
+import static android.view.InputDevice.SOURCE_MOUSE;
+import static android.view.MotionEvent.ACTION_HOVER_MOVE;
+import static android.view.MotionEvent.ACTION_MOVE;
+
+import android.view.MotionEvent;
+
+import com.android.server.accessibility.AccessibilityManagerService;
+
+/** MouseEventHandler handles mouse and stylus events that should move the viewport. */
+public final class MouseEventHandler {
+ private final FullScreenMagnificationController mFullScreenMagnificationController;
+
+ public MouseEventHandler(FullScreenMagnificationController fullScreenMagnificationController) {
+ mFullScreenMagnificationController = fullScreenMagnificationController;
+ }
+
+ /**
+ * Handles a mouse or stylus event, moving the magnifier if needed.
+ *
+ * @param event The mouse or stylus MotionEvent to consume
+ * @param displayId The display that is being magnified
+ */
+ public void onEvent(MotionEvent event, int displayId) {
+ if (event.getAction() == ACTION_HOVER_MOVE
+ || (event.getAction() == ACTION_MOVE && event.getSource() == SOURCE_MOUSE)) {
+ final float eventX = event.getX();
+ final float eventY = event.getY();
+
+ // Only move the viewport when over a magnified region.
+ // TODO(b/354696546): Ensure this doesn't stop the viewport from reaching the
+ // corners and edges at high levels of magnification.
+ if (mFullScreenMagnificationController.magnificationRegionContains(
+ displayId, eventX, eventY)) {
+ mFullScreenMagnificationController.setCenter(
+ displayId,
+ eventX,
+ eventY,
+ /* animate= */ false,
+ AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+ }
+ }
+ }
+}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
index 75d01f5..1818cdd 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
@@ -148,6 +148,10 @@
@Override
void onMotionEventInternal(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ if (event.getSource() != SOURCE_TOUCHSCREEN) {
+ // Window Magnification viewport doesn't move with mouse events (yet).
+ return;
+ }
// To keep InputEventConsistencyVerifiers within GestureDetectors happy.
mObservePanningScalingState.mPanningScalingHandler.onTouchEvent(event);
mCurrentState.onMotionEvent(event, rawEvent, policyFlags);
@@ -470,12 +474,14 @@
mDetectSingleFingerTripleTap
? MagnificationGestureMatcher.GESTURE_TRIPLE_TAP
: MagnificationGestureMatcher.GESTURE_SINGLE_TAP,
+ MagnificationGestureMatcher.getMagnificationMultiTapTimeout(mContext),
null));
mGestureMatchers.add(new MultiTapAndHold(context,
mDetectSingleFingerTripleTap ? 3 : 1,
mDetectSingleFingerTripleTap
? MagnificationGestureMatcher.GESTURE_TRIPLE_TAP_AND_HOLD
: MagnificationGestureMatcher.GESTURE_SINGLE_TAP_AND_HOLD,
+ MagnificationGestureMatcher.getMagnificationMultiTapTimeout(mContext),
null));
mGestureMatchers.add(new TwoFingersDownOrSwipe(context));
@@ -495,12 +501,16 @@
mDetectSingleFingerTripleTap ? 3 : 1,
mDetectSingleFingerTripleTap
? MagnificationGestureMatcher.GESTURE_TRIPLE_TAP
- : MagnificationGestureMatcher.GESTURE_SINGLE_TAP, null);
+ : MagnificationGestureMatcher.GESTURE_SINGLE_TAP,
+ MagnificationGestureMatcher.getMagnificationMultiTapTimeout(mContext),
+ null);
final MultiTapAndHold multiTapAndHold = new MultiTapAndHold(context,
mDetectSingleFingerTripleTap ? 3 : 1,
mDetectSingleFingerTripleTap
? MagnificationGestureMatcher.GESTURE_TRIPLE_TAP_AND_HOLD
- : MagnificationGestureMatcher.GESTURE_SINGLE_TAP_AND_HOLD, null);
+ : MagnificationGestureMatcher.GESTURE_SINGLE_TAP_AND_HOLD,
+ MagnificationGestureMatcher.getMagnificationMultiTapTimeout(mContext),
+ null);
mGesturesObserver = new MagnificationGesturesObserver(this,
new SimpleSwipe(context),
multiTap,
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 988a213..e57817f 100644
--- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
+++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
@@ -28,12 +28,12 @@
import android.app.WindowConfiguration;
import android.app.compat.CompatChanges;
import android.companion.virtual.VirtualDeviceManager.ActivityListener;
-import android.companion.virtual.flags.Flags;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.content.AttributionSource;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.IntentSender;
import android.content.pm.ActivityInfo;
import android.os.Build;
import android.os.Handler;
@@ -52,6 +52,7 @@
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
/**
* A controller to control the policies of the windows that can be displayed on the virtual display.
@@ -74,7 +75,7 @@
*/
public interface ActivityBlockedCallback {
/** Called when an activity is blocked.*/
- void onActivityBlocked(int displayId, ActivityInfo activityInfo);
+ void onActivityBlocked(int displayId, ActivityInfo activityInfo, IntentSender intentSender);
}
private static final ComponentName BLOCKED_APP_STREAMING_COMPONENT =
new ComponentName("android", BlockedAppStreamingActivity.class.getName());
@@ -108,12 +109,11 @@
private boolean mActivityLaunchAllowedByDefault;
@NonNull
@GuardedBy("mGenericWindowPolicyControllerLock")
- private final Set<ComponentName> mActivityPolicyExemptions;
+ private final ArraySet<ComponentName> mActivityPolicyExemptions;
private final boolean mCrossTaskNavigationAllowedByDefault;
@NonNull
private final ArraySet<ComponentName> mCrossTaskNavigationExemptions;
@Nullable
- private final ComponentName mPermissionDialogComponent;
private final Object mGenericWindowPolicyControllerLock = new Object();
@Nullable private final ActivityBlockedCallback mActivityBlockedCallback;
@@ -178,7 +178,6 @@
@NonNull Set<ComponentName> activityPolicyExemptions,
boolean crossTaskNavigationAllowedByDefault,
@NonNull Set<ComponentName> crossTaskNavigationExemptions,
- @Nullable ComponentName permissionDialogComponent,
@Nullable ActivityListener activityListener,
@Nullable ActivityBlockedCallback activityBlockedCallback,
@Nullable SecureWindowCallback secureWindowCallback,
@@ -190,10 +189,9 @@
mAttributionSource = attributionSource;
mAllowedUsers = allowedUsers;
mActivityLaunchAllowedByDefault = activityLaunchAllowedByDefault;
- mActivityPolicyExemptions = activityPolicyExemptions;
+ mActivityPolicyExemptions = new ArraySet<>(activityPolicyExemptions);
mCrossTaskNavigationAllowedByDefault = crossTaskNavigationAllowedByDefault;
mCrossTaskNavigationExemptions = new ArraySet<>(crossTaskNavigationExemptions);
- mPermissionDialogComponent = permissionDialogComponent;
mActivityBlockedCallback = activityBlockedCallback;
setInterestedWindowFlags(windowFlags, systemWindowFlags);
mActivityListener = activityListener;
@@ -286,29 +284,20 @@
@Override
public boolean canActivityBeLaunched(@NonNull ActivityInfo activityInfo,
@Nullable Intent intent, @WindowConfiguration.WindowingMode int windowingMode,
- int launchingFromDisplayId, boolean isNewTask) {
- if (Flags.interceptIntentsBeforeApplyingPolicy()) {
- if (mIntentListenerCallback != null && intent != null
- && mIntentListenerCallback.shouldInterceptIntent(intent)) {
- logActivityLaunchBlocked("Virtual device intercepting intent");
- return false;
- }
- if (!canContainActivity(activityInfo, windowingMode, launchingFromDisplayId,
- isNewTask)) {
- notifyActivityBlocked(activityInfo);
- return false;
- }
- } else {
- if (!canContainActivity(activityInfo, windowingMode, launchingFromDisplayId,
- isNewTask)) {
- notifyActivityBlocked(activityInfo);
- return false;
- }
- if (mIntentListenerCallback != null && intent != null
- && mIntentListenerCallback.shouldInterceptIntent(intent)) {
- logActivityLaunchBlocked("Virtual device intercepting intent");
- return false;
- }
+ int launchingFromDisplayId, boolean isNewTask, boolean isResultExpected,
+ @Nullable Supplier<IntentSender> intentSender) {
+ if (mIntentListenerCallback != null && intent != null
+ && mIntentListenerCallback.shouldInterceptIntent(intent)) {
+ logActivityLaunchBlocked("Virtual device intercepting intent");
+ return false;
+ }
+ if (!canContainActivity(activityInfo, windowingMode, launchingFromDisplayId,
+ isNewTask)) {
+ // If the sender of the original intent expects a result to be reported, do not pass the
+ // intent sender to the client callback. As the launch is blocked, the caller already
+ // received that activity result.
+ notifyActivityBlocked(activityInfo, isResultExpected ? null : intentSender);
+ return false;
}
return true;
}
@@ -370,14 +359,6 @@
return false;
}
- // mPermissionDialogComponent being null means we don't want to block permission Dialogs
- // based on FLAG_STREAM_PERMISSIONS
- if (mPermissionDialogComponent != null
- && mPermissionDialogComponent.equals(activityComponent)) {
- logActivityLaunchBlocked("Permission dialog not allowed on virtual device");
- return false;
- }
-
return true;
}
@@ -406,7 +387,7 @@
// TODO(b/201712607): Add checks for the apps that use SurfaceView#setSecure.
if ((windowFlags & FLAG_SECURE) != 0
|| (systemWindowFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
- notifyActivityBlocked(activityInfo);
+ notifyActivityBlocked(activityInfo, /* intentSender= */ null);
return false;
}
}
@@ -479,19 +460,19 @@
&& mDisplayCategories.contains(activityInfo.requiredDisplayCategory);
}
- private void notifyActivityBlocked(ActivityInfo activityInfo) {
+ private void notifyActivityBlocked(
+ ActivityInfo activityInfo, Supplier<IntentSender> intentSender) {
int displayId = waitAndGetDisplayId();
// Don't trigger activity blocked callback for mirror displays, because we can't show
// any activity or presentation on it anyway.
if (!waitAndGetIsMirrorDisplay() && mActivityBlockedCallback != null
&& displayId != INVALID_DISPLAY) {
- mActivityBlockedCallback.onActivityBlocked(displayId, activityInfo);
+ mActivityBlockedCallback.onActivityBlocked(displayId, activityInfo,
+ intentSender == null ? null : intentSender.get());
}
- if (android.companion.virtualdevice.flags.Flags.metricsCollection()) {
- Counter.logIncrementWithUid(
- "virtual_devices.value_activity_blocked_count",
- mAttributionSource.getUid());
- }
+ Counter.logIncrementWithUid(
+ "virtual_devices.value_activity_blocked_count",
+ mAttributionSource.getUid());
}
private static boolean isAllowedByPolicy(boolean allowedByDefault,
diff --git a/services/companion/java/com/android/server/companion/virtual/InputController.java b/services/companion/java/com/android/server/companion/virtual/InputController.java
index d091ce8..8da58cf 100644
--- a/services/companion/java/com/android/server/companion/virtual/InputController.java
+++ b/services/companion/java/com/android/server/companion/virtual/InputController.java
@@ -842,11 +842,9 @@
deviceName, inputDeviceId));
}
- if (android.companion.virtualdevice.flags.Flags.metricsCollection()) {
- String metricId = getMetricIdForInputType(type);
- if (metricId != null) {
- Counter.logIncrementWithUid(metricId, mAttributionSource.getUid());
- }
+ String metricId = getMetricIdForInputType(type);
+ if (metricId != null) {
+ Counter.logIncrementWithUid(metricId, mAttributionSource.getUid());
}
}
diff --git a/services/companion/java/com/android/server/companion/virtual/SensorController.java b/services/companion/java/com/android/server/companion/virtual/SensorController.java
index 0655685..8d075db 100644
--- a/services/companion/java/com/android/server/companion/virtual/SensorController.java
+++ b/services/companion/java/com/android/server/companion/virtual/SensorController.java
@@ -145,11 +145,9 @@
mSensorDescriptors.put(sensorToken, sensorDescriptor);
mVirtualSensors.put(handle, sensor);
}
- if (android.companion.virtualdevice.flags.Flags.metricsCollection()) {
- Counter.logIncrementWithUid(
- "virtual_devices.value_virtual_sensors_created_count",
- mAttributionSource.getUid());
- }
+ Counter.logIncrementWithUid(
+ "virtual_devices.value_virtual_sensors_created_count",
+ mAttributionSource.getUid());
}
boolean sendSensorEvent(@NonNull IBinder token, @NonNull VirtualSensorEvent event) {
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
index ee7d0ae..2db5443 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -29,8 +29,6 @@
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_CLIPBOARD;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_RECENTS;
import static android.companion.virtualdevice.flags.Flags.virtualCameraServiceDiscovery;
-import static android.companion.virtualdevice.flags.Flags.intentInterceptionActionMatchingFix;
-import static android.content.pm.PackageManager.ACTION_REQUEST_PERMISSIONS;
import android.annotation.EnforcePermission;
import android.annotation.NonNull;
@@ -62,6 +60,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.IntentSender;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.graphics.PointF;
@@ -208,7 +207,6 @@
@GuardedBy("mVirtualDeviceLock")
@NonNull
private final Set<ComponentName> mActivityPolicyExemptions;
- private final ComponentName mPermissionDialogComponent;
private ActivityListener createListenerAdapter() {
return new ActivityListener() {
@@ -244,9 +242,11 @@
@Override
public void onActivityLaunchBlocked(int displayId,
- @NonNull ComponentName componentName, @UserIdInt int userId) {
+ @NonNull ComponentName componentName, @UserIdInt int userId,
+ @Nullable IntentSender intentSender) {
try {
- mActivityListener.onActivityLaunchBlocked(displayId, componentName, userId);
+ mActivityListener.onActivityLaunchBlocked(
+ displayId, componentName, userId, intentSender);
} catch (RemoteException e) {
Slog.w(TAG, "Unable to call mActivityListener for display: " + displayId, e);
}
@@ -343,11 +343,6 @@
if (mCameraAccessController != null) {
mCameraAccessController.startObservingIfNeeded();
}
- if (!Flags.streamPermissions()) {
- mPermissionDialogComponent = getPermissionDialogComponent();
- } else {
- mPermissionDialogComponent = null;
- }
mVirtualCameraController = virtualCameraController;
try {
token.linkToDeath(this, 0);
@@ -558,6 +553,36 @@
}
}
+ @Override // Binder call
+ @EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
+ public void addActivityPolicyExemptionForDisplay(
+ int displayId, @NonNull ComponentName componentName) {
+ super.addActivityPolicyExemptionForDisplay_enforcePermission();
+ if (!android.companion.virtualdevice.flags.Flags.activityControlApi()) {
+ return;
+ }
+ synchronized (mVirtualDeviceLock) {
+ checkDisplayOwnedByVirtualDeviceLocked(displayId);
+ mVirtualDisplays.get(displayId).getWindowPolicyController()
+ .addActivityPolicyExemption(componentName);
+ }
+ }
+
+ @Override // Binder call
+ @EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
+ public void removeActivityPolicyExemptionForDisplay(
+ int displayId, @NonNull ComponentName componentName) {
+ super.removeActivityPolicyExemptionForDisplay_enforcePermission();
+ if (!android.companion.virtualdevice.flags.Flags.activityControlApi()) {
+ return;
+ }
+ synchronized (mVirtualDeviceLock) {
+ checkDisplayOwnedByVirtualDeviceLocked(displayId);
+ mVirtualDisplays.get(displayId).getWindowPolicyController()
+ .removeActivityPolicyExemption(componentName);
+ }
+ }
+
private void sendPendingIntent(int displayId, PendingIntent pendingIntent)
throws PendingIntent.CanceledException {
final ActivityOptions options = ActivityOptions.makeBasic().setLaunchDisplayId(displayId);
@@ -657,12 +682,7 @@
@Nullable IAudioConfigChangedCallback configChangedCallback) {
super.onAudioSessionStarting_enforcePermission();
synchronized (mVirtualDeviceLock) {
- if (!mVirtualDisplays.contains(displayId)) {
- throw new SecurityException(
- "Cannot start audio session for a display not associated with this virtual "
- + "device");
- }
-
+ checkDisplayOwnedByVirtualDeviceLocked(displayId);
if (mVirtualAudioController == null) {
mVirtualAudioController = new VirtualAudioController(mContext, mAttributionSource);
GenericWindowPolicyController gwpc = mVirtualDisplays.get(
@@ -706,6 +726,9 @@
break;
case POLICY_TYPE_ACTIVITY:
synchronized (mVirtualDeviceLock) {
+ if (getDevicePolicy(policyType) != devicePolicy) {
+ mActivityPolicyExemptions.clear();
+ }
mDevicePolicies.put(policyType, devicePolicy);
for (int i = 0; i < mVirtualDisplays.size(); i++) {
mVirtualDisplays.valueAt(i).getWindowPolicyController()
@@ -736,6 +759,33 @@
@Override // Binder call
@EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
+ public void setDevicePolicyForDisplay(int displayId,
+ @VirtualDeviceParams.DynamicDisplayPolicyType int policyType,
+ @VirtualDeviceParams.DevicePolicy int devicePolicy) {
+ super.setDevicePolicyForDisplay_enforcePermission();
+ if (!android.companion.virtualdevice.flags.Flags.activityControlApi()) {
+ return;
+ }
+ synchronized (mVirtualDeviceLock) {
+ checkDisplayOwnedByVirtualDeviceLocked(displayId);
+ switch (policyType) {
+ case POLICY_TYPE_RECENTS:
+ mVirtualDisplays.get(displayId).getWindowPolicyController()
+ .setShowInHostDeviceRecents(devicePolicy == DEVICE_POLICY_DEFAULT);
+ break;
+ case POLICY_TYPE_ACTIVITY:
+ mVirtualDisplays.get(displayId).getWindowPolicyController()
+ .setActivityLaunchDefaultAllowed(devicePolicy == DEVICE_POLICY_DEFAULT);
+ break;
+ default:
+ throw new IllegalArgumentException("Device policy " + policyType
+ + " cannot be changed for a specific display. ");
+ }
+ }
+ }
+
+ @Override // Binder call
+ @EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
public void createVirtualDpad(VirtualDpadConfig config, @NonNull IBinder deviceToken) {
super.createVirtualDpad_enforcePermission();
Objects.requireNonNull(config);
@@ -1243,7 +1293,6 @@
/* crossTaskNavigationExemptions= */crossTaskNavigationAllowedByDefault
? mParams.getBlockedCrossTaskNavigations()
: mParams.getAllowedCrossTaskNavigations(),
- mPermissionDialogComponent,
mActivityListenerAdapter,
this::onActivityBlocked,
this::onSecureWindowShown,
@@ -1255,13 +1304,6 @@
return gwpc;
}
- private ComponentName getPermissionDialogComponent() {
- Intent intent = new Intent(ACTION_REQUEST_PERMISSIONS);
- PackageManager packageManager = mContext.getPackageManager();
- intent.setPackage(packageManager.getPermissionControllerPackageName());
- return intent.resolveActivity(packageManager);
- }
-
int createVirtualDisplay(@NonNull VirtualDisplayConfig virtualDisplayConfig,
@NonNull IVirtualDisplayCallback callback, String packageName) {
GenericWindowPolicyController gwpc;
@@ -1273,7 +1315,7 @@
this, gwpc, packageName);
gwpc.setDisplayId(displayId, /* isMirrorDisplay= */ Flags.interactiveScreenMirror()
&& mDisplayManagerInternal.getDisplayIdToMirror(displayId)
- != Display.INVALID_DISPLAY);
+ != Display.INVALID_DISPLAY);
boolean showPointer;
synchronized (mVirtualDeviceLock) {
@@ -1304,11 +1346,9 @@
Binder.restoreCallingIdentity(token);
}
- if (android.companion.virtualdevice.flags.Flags.metricsCollection()) {
- Counter.logIncrementWithUid(
- "virtual_devices.value_virtual_display_created_count",
- mAttributionSource.getUid());
- }
+ Counter.logIncrementWithUid(
+ "virtual_devices.value_virtual_display_created_count",
+ mAttributionSource.getUid());
return displayId;
}
@@ -1327,7 +1367,8 @@
}
@RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
- private void onActivityBlocked(int displayId, ActivityInfo activityInfo) {
+ private void onActivityBlocked(int displayId, ActivityInfo activityInfo,
+ IntentSender intentSender) {
Intent intent = BlockedAppStreamingActivity.createIntent(activityInfo, getDisplayName());
if (shouldShowBlockedActivityDialog(
activityInfo.getComponentName(), intent.getComponent())) {
@@ -1343,7 +1384,8 @@
displayId,
activityInfo.getComponentName(),
UserHandle.getUserHandleForUid(
- activityInfo.applicationInfo.uid).getIdentifier());
+ activityInfo.applicationInfo.uid).getIdentifier(),
+ intentSender);
}
}
@@ -1376,11 +1418,9 @@
showToastWhereUidIsRunning(uid, com.android.internal.R.string.vdm_secure_window,
Toast.LENGTH_LONG, mContext.getMainLooper());
- if (android.companion.virtualdevice.flags.Flags.metricsCollection()) {
- Counter.logIncrementWithUid(
- "virtual_devices.value_secure_window_blocked_count",
- mAttributionSource.getUid());
- }
+ Counter.logIncrementWithUid(
+ "virtual_devices.value_secure_window_blocked_count",
+ mAttributionSource.getUid());
}
}
@@ -1441,20 +1481,24 @@
@SuppressWarnings("AndroidFrameworkRequiresPermission")
private void checkVirtualInputDeviceDisplayIdAssociation(int displayId) {
+ // The INJECT_EVENTS permission allows for injecting input to any window / display.
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.INJECT_EVENTS)
- == PackageManager.PERMISSION_GRANTED) {
- // The INJECT_EVENTS permission allows for injecting input to any window / display.
- return;
- }
- synchronized (mVirtualDeviceLock) {
- if (!mVirtualDisplays.contains(displayId)) {
- throw new SecurityException(
- "Cannot create a virtual input device for display " + displayId
- + " which not associated with this virtual device");
+ != PackageManager.PERMISSION_GRANTED) {
+ synchronized (mVirtualDeviceLock) {
+ checkDisplayOwnedByVirtualDeviceLocked(displayId);
}
}
}
+ @GuardedBy("mVirtualDeviceLock")
+ private void checkDisplayOwnedByVirtualDeviceLocked(int displayId) {
+ if (!mVirtualDisplays.contains(displayId)) {
+ throw new SecurityException(
+ "Invalid displayId: Display " + displayId
+ + " is not associated with this virtual device");
+ }
+ }
+
/**
* Release resources tied to virtual display owned by this VirtualDevice instance.
*
@@ -1579,8 +1623,8 @@
// Explicitly match the actions because the intent filter will match any intent
// without an explicit action. If the intent has no action, then require that there
// are no actions specified in the filter either.
- boolean explicitActionMatch = !intentInterceptionActionMatchingFix()
- || intent.getAction() != null || intentFilter.countActions() == 0;
+ boolean explicitActionMatch =
+ intent.getAction() != null || intentFilter.countActions() == 0;
if (explicitActionMatch && intentFilter.match(
intent.getAction(), intent.getType(), intent.getScheme(), intent.getData(),
intent.getCategories(), TAG) >= 0) {
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
index 1be1d2b..3cd1ca4 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
@@ -474,9 +474,7 @@
deviceId,
cameraAccessController, mPendingTrampolineCallback, activityListener,
soundEffectListener, runningAppsChangedCallback, params);
- if (Flags.expressMetrics()) {
- Counter.logIncrement("virtual_devices.value_virtual_devices_created_count");
- }
+ Counter.logIncrement("virtual_devices.value_virtual_devices_created_count");
synchronized (mVirtualDeviceManagerLock) {
if (!Flags.persistentDeviceIdApi() && mVirtualDevices.size() == 0) {
@@ -500,11 +498,9 @@
}
});
}
- if (android.companion.virtualdevice.flags.Flags.metricsCollection()) {
- Counter.logIncrementWithUid(
- "virtual_devices.value_virtual_devices_created_with_uid_count",
- attributionSource.getUid());
- }
+ Counter.logIncrementWithUid(
+ "virtual_devices.value_virtual_devices_created_with_uid_count",
+ attributionSource.getUid());
return virtualDevice;
}
diff --git a/services/companion/java/com/android/server/companion/virtual/audio/VirtualAudioController.java b/services/companion/java/com/android/server/companion/virtual/audio/VirtualAudioController.java
index 4bffb76..d3b3945 100644
--- a/services/companion/java/com/android/server/companion/virtual/audio/VirtualAudioController.java
+++ b/services/companion/java/com/android/server/companion/virtual/audio/VirtualAudioController.java
@@ -77,11 +77,9 @@
mAudioPlaybackDetector = new AudioPlaybackDetector(context);
mAudioRecordingDetector = new AudioRecordingDetector(context);
- if (android.companion.virtualdevice.flags.Flags.metricsCollection()) {
- Counter.logIncrementWithUid(
- "virtual_devices.value_virtual_audio_created_count",
- attributionSource.getUid());
- }
+ Counter.logIncrementWithUid(
+ "virtual_devices.value_virtual_audio_created_count",
+ attributionSource.getUid());
}
/**
diff --git a/services/companion/java/com/android/server/companion/virtual/camera/VirtualCameraController.java b/services/companion/java/com/android/server/companion/virtual/camera/VirtualCameraController.java
index 62efafb..7b81ef3 100644
--- a/services/companion/java/com/android/server/companion/virtual/camera/VirtualCameraController.java
+++ b/services/companion/java/com/android/server/companion/virtual/camera/VirtualCameraController.java
@@ -102,11 +102,9 @@
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
- if (android.companion.virtualdevice.flags.Flags.metricsCollection()) {
- Counter.logIncrementWithUid(
- "virtual_devices.value_virtual_camera_created_count",
- attributionSource.getUid());
- }
+ Counter.logIncrementWithUid(
+ "virtual_devices.value_virtual_camera_created_count",
+ attributionSource.getUid());
}
/**
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 363c1d8..89d7961 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -30,6 +30,18 @@
],
}
+filegroup {
+ name: "services.core-aidl-sources",
+ srcs: [
+ ":dumpstate_aidl",
+ ":framework_native_aidl",
+ ":gsiservice_aidl",
+ ":installd_aidl",
+ ":storaged_aidl",
+ ":vold_aidl",
+ ],
+}
+
java_library_static {
name: "services-config-update",
srcs: [
@@ -120,14 +132,9 @@
":android.hardware.tv.hdmi.earc-V1-java-source",
":statslog-art-java-gen",
":statslog-contexthub-java-gen",
+ ":services.core-aidl-sources",
":services.core-sources",
":services.core.protologsrc",
- ":dumpstate_aidl",
- ":framework_native_aidl",
- ":gsiservice_aidl",
- ":installd_aidl",
- ":storaged_aidl",
- ":vold_aidl",
":platform-compat-config",
":platform-compat-overrides",
":display-device-config",
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 1ccc48d..2de4482 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -157,7 +157,7 @@
private int mLastMaxChargingVoltage;
private int mLastChargeCounter;
private int mLastBatteryCycleCount;
- private int mLastCharingState;
+ private int mLastChargingState;
/**
* The last seen charging policy. This requires the
* {@link android.Manifest.permission#BATTERY_STATS} permission and should therefore not be
@@ -555,7 +555,7 @@
|| mHealthInfo.batteryChargeCounterUah != mLastChargeCounter
|| mInvalidCharger != mLastInvalidCharger
|| mHealthInfo.batteryCycleCount != mLastBatteryCycleCount
- || mHealthInfo.chargingState != mLastCharingState)) {
+ || mHealthInfo.chargingState != mLastChargingState)) {
if (mPlugType != mLastPlugType) {
if (mLastPlugType == BATTERY_PLUGGED_NONE) {
@@ -738,7 +738,7 @@
mLastBatteryLevelCritical = mBatteryLevelCritical;
mLastInvalidCharger = mInvalidCharger;
mLastBatteryCycleCount = mHealthInfo.batteryCycleCount;
- mLastCharingState = mHealthInfo.chargingState;
+ mLastChargingState = mHealthInfo.chargingState;
}
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 33cf842..79e09d7 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -2229,7 +2229,7 @@
for (Record r : mRecords) {
if (r.matchTelephonyCallbackEvent(
TelephonyCallback.EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED)
- && idMatch(r, subId, phoneId)) {
+ && idMatchRelaxed(r, subId, phoneId)) {
try {
r.callback.onPreciseDataConnectionStateChanged(preciseState);
} catch (RemoteException ex) {
@@ -3535,6 +3535,10 @@
synchronized (mRecords) {
int phoneId = getPhoneIdFromSubId(subId);
+ if (!validatePhoneId(phoneId)) {
+ loge("Invalid phone ID " + phoneId + " for " + subId);
+ return;
+ }
mCarrierRoamingNtnMode[phoneId] = active;
for (Record r : mRecords) {
if (r.matchTelephonyCallbackEvent(
@@ -3582,6 +3586,10 @@
synchronized (mRecords) {
int phoneId = getPhoneIdFromSubId(subId);
+ if (!validatePhoneId(phoneId)) {
+ loge("Invalid phone ID " + phoneId + " for " + subId);
+ return;
+ }
mCarrierRoamingNtnEligible[phoneId] = eligible;
for (Record r : mRecords) {
if (r.matchTelephonyCallbackEvent(
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 69478bb..2af5316 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -186,6 +186,12 @@
final Context mContext;
+ private static final int[] INTERESTING_APP_OPS = new int[] {
+ AppOpsManager.OP_GET_ACCOUNTS,
+ AppOpsManager.OP_READ_CONTACTS,
+ AppOpsManager.OP_WRITE_CONTACTS,
+ };
+
private final PackageManager mPackageManager;
private final AppOpsManager mAppOpsManager;
private UserManager mUserManager;
@@ -389,74 +395,48 @@
}.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
// Cancel account request notification if an app op was preventing the account access
- mAppOpsManager.startWatchingMode(AppOpsManager.OP_GET_ACCOUNTS, null,
- new AppOpsManager.OnOpChangedInternalListener() {
- @Override
- public void onOpChanged(int op, String packageName) {
- try {
- final int userId = ActivityManager.getCurrentUser();
- final int uid = mPackageManager.getPackageUidAsUser(packageName, userId);
- final int mode = mAppOpsManager.checkOpNoThrow(
- AppOpsManager.OP_GET_ACCOUNTS, uid, packageName);
- if (mode == AppOpsManager.MODE_ALLOWED) {
- final long identity = Binder.clearCallingIdentity();
- try {
- UserAccounts accounts = getUserAccounts(userId);
- cancelAccountAccessRequestNotificationIfNeeded(
- packageName, uid, true, accounts);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
- } catch (NameNotFoundException e) {
- /* ignore */
- } catch (SQLiteCantOpenDatabaseException e) {
- Log.w(TAG, "Can't read accounts database", e);
- return;
- }
- }
- });
+ for (int i = 0; i < INTERESTING_APP_OPS.length; ++i) {
+ mAppOpsManager.startWatchingMode(INTERESTING_APP_OPS[i], null,
+ new OnInterestingAppOpChangedListener());
+ }
- // Cancel account request notification if a permission was preventing the account access
- mPackageManager.addOnPermissionsChangeListener(
- (int uid) -> {
- // Permission changes cause requires updating accounts cache.
+ // Clear the accounts cache on permission changes.
+ // The specific permissions we care about are backed by AppOps, so just
+ // let the change events on those handle clearing any notifications.
+ mPackageManager.addOnPermissionsChangeListener((int uid) -> {
AccountManager.invalidateLocalAccountsDataCaches();
-
- Account[] accounts = null;
- String[] packageNames = mPackageManager.getPackagesForUid(uid);
- if (packageNames != null) {
- final int userId = UserHandle.getUserId(uid);
- final long identity = Binder.clearCallingIdentity();
- try {
- for (String packageName : packageNames) {
- // if app asked for permission we need to cancel notification even
- // for O+ applications.
- if (mPackageManager.checkPermission(
- Manifest.permission.GET_ACCOUNTS,
- packageName) != PackageManager.PERMISSION_GRANTED) {
- continue;
- }
-
- if (accounts == null) {
- accounts = getAccountsOrEmptyArray(null, userId, "android");
- if (ArrayUtils.isEmpty(accounts)) {
- return;
- }
- }
- UserAccounts userAccounts = getUserAccounts(UserHandle.getUserId(uid));
- for (Account account : accounts) {
- cancelAccountAccessRequestNotificationIfNeeded(
- account, uid, packageName, true, userAccounts);
- }
- }
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
});
}
+ private class OnInterestingAppOpChangedListener
+ extends AppOpsManager.OnOpChangedInternalListener {
+ @Override
+ public void onOpChanged(int op, String packageName) {
+ final int userId = ActivityManager.getCurrentUser();
+ final int packageUid;
+ try {
+ packageUid = mPackageManager.getPackageUidAsUser(packageName, userId);
+ } catch (NameNotFoundException e) {
+ /* ignore */
+ return;
+ }
+
+ final int mode = mAppOpsManager.checkOpNoThrow(op, packageUid, packageName);
+ if (mode != AppOpsManager.MODE_ALLOWED) {
+ return;
+ }
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ cancelAccountAccessRequestNotificationIfNeeded(
+ packageName, packageUid, true, getUserAccounts(userId));
+ } catch (SQLiteCantOpenDatabaseException e) {
+ Log.w(TAG, "Can't read accounts database", e);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
boolean getBindInstantServiceAllowed(int userId) {
return mAuthenticatorCache.getBindInstantServiceAllowed(userId);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index cf0befa..9d8f337 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1716,6 +1716,12 @@
*/
@Nullable volatile ContentCaptureManagerInternal mContentCaptureService;
+ /**
+ * The interface to the freezer.
+ */
+ @NonNull
+ private final Freezer mFreezer;
+
/*
* The default duration for the binder heavy hitter auto sampler
*/
@@ -2506,6 +2512,7 @@
@Nullable UserController userController) {
mInjector = injector;
mContext = mInjector.getContext();
+ mFreezer = injector.getFreezer();
mUiContext = null;
mAppErrors = injector.getAppErrors();
mPackageWatchdog = null;
@@ -2555,6 +2562,7 @@
LockGuard.installLock(this, LockGuard.INDEX_ACTIVITY);
mInjector = new Injector(systemContext);
mContext = systemContext;
+ mFreezer = mInjector.getFreezer();
mFactoryTest = FactoryTest.getMode();
mSystemThread = ActivityThread.currentActivityThread();
@@ -18436,6 +18444,23 @@
implements ActivityManagerLocal {
@Override
+ public void addFrozenProcessListener(int pid, @NonNull Executor executor,
+ @NonNull FrozenProcessListener listener) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(listener);
+ synchronized (mProcLock) {
+ final ProcessRecord app;
+ synchronized (mPidsSelfLocked) {
+ app = mPidsSelfLocked.get(pid);
+ }
+ if (app != null) {
+ mOomAdjuster.mCachedAppOptimizer.addFrozenProcessListener(app, executor,
+ listener);
+ }
+ }
+ }
+
+ @Override
public List<PendingIntentStats> getPendingIntentStats() {
return mPendingIntentController.dumpPendingIntentStatsForStatsd();
}
@@ -20919,6 +20944,11 @@
public IntentFirewall getIntentFirewall() {
return null;
}
+
+ /** @return the default Freezer. */
+ public Freezer getFreezer() {
+ return new Freezer();
+ }
}
@Override
@@ -21022,7 +21052,7 @@
final long token = Binder.clearCallingIdentity();
try {
- return CachedAppOptimizer.isFreezerSupported();
+ return mFreezer.isFreezerSupported();
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -21177,4 +21207,9 @@
void clearPendingTopAppLocked() {
mPendingStartActivityUids.clear();
}
+
+ @NonNull
+ Freezer getFreezer() {
+ return mFreezer;
+ }
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index bbd4323..0e19347 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -1234,8 +1234,7 @@
if (freeze) {
mInternal.mOomAdjuster.mCachedAppOptimizer.forceFreezeAppAsyncLSP(proc);
} else {
- mInternal.mOomAdjuster.mCachedAppOptimizer.unfreezeAppInternalLSP(proc, 0,
- true);
+ mInternal.mOomAdjuster.mCachedAppOptimizer.unfreezeAppLSP(proc, 0, true);
}
}
}
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index ee7033e..415f78a 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -65,7 +65,6 @@
import com.android.server.LocalServices;
import com.android.server.PackageWatchdog;
import com.android.server.pm.UserManagerInternal;
-import com.android.server.pm.UserManagerService;
import com.android.server.usage.AppStandbyInternal;
import com.android.server.wm.WindowProcessController;
@@ -1027,7 +1026,8 @@
isBackground &= (userId != profileId);
}
int visibleUserId = getVisibleUserId(userId);
- boolean isVisibleUser = isVisibleBackgroundUser(visibleUserId);
+ boolean isVisibleUser = LocalServices.getService(UserManagerInternal.class)
+ .isVisibleBackgroundFullUser(visibleUserId);
boolean showBackground = Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.ANR_SHOW_BACKGROUND, 0, visibleUserId) != 0;
if (isBackground && !showBackground && !isVisibleUser) {
@@ -1050,7 +1050,7 @@
mContext.getContentResolver(),
Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
0,
- mService.mUserController.getCurrentUserId()) != 0;
+ visibleUserId) != 0;
final String packageName = proc.info.packageName;
final boolean crashSilenced = mAppsNotReportingCrashes != null
&& mAppsNotReportingCrashes.contains(proc.info.packageName);
@@ -1183,26 +1183,6 @@
}
/**
- * Checks if the given user is a visible background user, which is a full, background user
- * assigned to secondary displays on the devices that have
- * {@link UserManager#isVisibleBackgroundUsersEnabled()
- * config_multiuserVisibleBackgroundUsers enabled} (for example, passenger users on
- * automotive builds, using the display associated with their seats).
- *
- * @see UserManager#isUserVisible()
- */
- private boolean isVisibleBackgroundUser(int userId) {
- if (!UserManager.isVisibleBackgroundUsersEnabled()) {
- return false;
- }
- boolean isForeground = mService.mUserController.getCurrentUserId() == userId;
- boolean isProfile = UserManagerService.getInstance().isProfile(userId);
- boolean isVisible = LocalServices.getService(UserManagerInternal.class)
- .isUserVisible(userId);
- return isVisible && !isForeground && !isProfile;
- }
-
- /**
* Information about a process that is currently marked as bad.
*/
static final class BadProcessInfo {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 03fbfd37..6333159 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -620,6 +620,10 @@
private void setPowerStatsThrottlePeriods(BatteryStatsImpl.BatteryStatsConfig.Builder builder,
String configString) {
+ if (configString == null) {
+ return;
+ }
+
Matcher matcher = Pattern.compile("([^:]+):(\\d+)\\s*").matcher(configString);
while (matcher.find()) {
String powerComponentName = matcher.group(1);
@@ -1256,7 +1260,14 @@
.setMinConsumedPowerThreshold(minConsumedPowerThreshold)
.build();
bus = getBatteryUsageStats(List.of(query)).get(0);
- return new StatsPerUidLogger(new FrameworkStatsLogger()).logStats(bus, data);
+ final int pullResult =
+ new StatsPerUidLogger(new FrameworkStatsLogger()).logStats(bus, data);
+ try {
+ bus.close();
+ } catch (IOException e) {
+ Slog.w(TAG, "Failure close BatteryUsageStats", e);
+ }
+ return pullResult;
}
default:
throw new UnsupportedOperationException("Unknown tagId=" + atomTag);
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 1c4ffbb..8f52f67 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -49,6 +49,7 @@
import android.annotation.IntDef;
import android.annotation.UptimeMillisLong;
import android.app.ActivityManager;
+import android.app.ActivityManagerInternal.FrozenProcessListener;
import android.app.ActivityManagerInternal.OomAdjReason;
import android.app.ActivityThread;
import android.app.ApplicationExitInfo;
@@ -99,6 +100,7 @@
import java.util.Map;
import java.util.Random;
import java.util.Set;
+import java.util.concurrent.Executor;
public final class CachedAppOptimizer {
@@ -664,6 +666,8 @@
private final ProcessDependencies mProcessDependencies;
private final ProcLocksReader mProcLocksReader;
+ private final Freezer mFreezer;
+
public CachedAppOptimizer(ActivityManagerService am) {
this(am, null, new DefaultProcessDependencies());
}
@@ -680,6 +684,7 @@
mTestCallback = callback;
mSettingsObserver = new SettingsContentObserver();
mProcLocksReader = new ProcLocksReader();
+ mFreezer = mAm.getFreezer();
}
/**
@@ -1050,89 +1055,6 @@
}
/**
- * Informs binder that a process is about to be frozen. If freezer is enabled on a process via
- * this method, this method will synchronously dispatch all pending transactions to the
- * specified pid. This method will not add significant latencies when unfreezing.
- * After freezing binder calls, binder will block all transaction to the frozen pid, and return
- * an error to the sending process.
- *
- * @param pid the target pid for which binder transactions are to be frozen
- * @param freeze specifies whether to flush transactions and then freeze (true) or unfreeze
- * binder for the specificed pid.
- * @param timeoutMs the timeout in milliseconds to wait for the binder interface to freeze
- * before giving up.
- *
- * @throws RuntimeException in case a flush/freeze operation could not complete successfully.
- * @return 0 if success, or -EAGAIN indicating there's pending transaction.
- */
- public static native int freezeBinder(int pid, boolean freeze, int timeoutMs);
-
- /**
- * Retrieves binder freeze info about a process.
- * @param pid the pid for which binder freeze info is to be retrieved.
- *
- * @throws RuntimeException if the operation could not complete successfully.
- * @return a bit field reporting the binder freeze info for the process.
- */
- private static native int getBinderFreezeInfo(int pid);
-
- /**
- * Returns the path to be checked to verify whether the freezer is supported by this system.
- * @return absolute path to the file
- */
- private static native String getFreezerCheckPath();
-
- /**
- * Check if task_profiles.json includes valid freezer profiles and actions
- * @return false if there are invalid profiles or actions
- */
- private static native boolean isFreezerProfileValid();
-
- /**
- * Determines whether the freezer is supported by this system
- */
- public static boolean isFreezerSupported() {
- boolean supported = false;
- FileReader fr = null;
-
- try {
- String path = getFreezerCheckPath();
- Slog.d(TAG_AM, "Checking cgroup freezer: " + path);
- fr = new FileReader(path);
- char state = (char) fr.read();
-
- if (state == '1' || state == '0') {
- // Also check freezer binder ioctl
- Slog.d(TAG_AM, "Checking binder freezer ioctl");
- getBinderFreezeInfo(Process.myPid());
-
- // Check if task_profiles.json contains invalid profiles
- Slog.d(TAG_AM, "Checking freezer profiles");
- supported = isFreezerProfileValid();
- } else {
- Slog.e(TAG_AM, "Unexpected value in cgroup.freeze");
- }
- } catch (java.io.FileNotFoundException e) {
- Slog.w(TAG_AM, "File cgroup.freeze not present");
- } catch (RuntimeException e) {
- Slog.w(TAG_AM, "Unable to read freezer info");
- } catch (Exception e) {
- Slog.w(TAG_AM, "Unable to read cgroup.freeze: " + e.toString());
- }
-
- if (fr != null) {
- try {
- fr.close();
- } catch (java.io.IOException e) {
- Slog.e(TAG_AM, "Exception closing cgroup.freeze: " + e.toString());
- }
- }
-
- Slog.d(TAG_AM, "Freezer supported: " + supported);
- return supported;
- }
-
- /**
* Reads the flag value from DeviceConfig to determine whether app freezer
* should be enabled, and starts the freeze/compaction thread if needed.
*/
@@ -1146,7 +1068,7 @@
} else if ("enabled".equals(configOverride)
|| DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
KEY_USE_FREEZER, DEFAULT_USE_FREEZER)) {
- mUseFreezer = isFreezerSupported();
+ mUseFreezer = mFreezer.isFreezerSupported();
updateFreezerDebounceTimeout();
updateFreezerExemptInstPkg();
} else {
@@ -1486,8 +1408,15 @@
}
}
+ /**
+ * Returns true if the app was frozen and became unfrozen, otherwise false.
+ *
+ * Do not call this directly. It will unfreeze a process but it will not send out any
+ * notifications. Instead call unfreezeAppLSP().
+ */
@GuardedBy({"mAm", "mProcLock", "mFreezerLock"})
- void unfreezeAppInternalLSP(ProcessRecord app, @UnfreezeReason int reason, boolean force) {
+ private boolean unfreezeAppInternalLSP(ProcessRecord app, @UnfreezeReason int reason,
+ boolean force) {
final int pid = app.getPid();
final ProcessCachedOptimizerRecord opt = app.mOptRecord;
boolean sticky = opt.isFreezeSticky();
@@ -1498,7 +1427,7 @@
"Skip unfreezing because frozen state is sticky pid=" + pid + " "
+ app.processName);
}
- return;
+ return false;
}
boolean processFreezableChangeReported = false;
if (opt.isPendingFreeze()) {
@@ -1520,7 +1449,7 @@
opt.setFreezerOverride(false);
if (pid == 0 || !opt.isFrozen()) {
- return;
+ return false;
}
// Unfreeze the binder interface first, to avoid transactions triggered by timers fired
@@ -1528,7 +1457,7 @@
boolean processKilled = false;
try {
- int freezeInfo = getBinderFreezeInfo(pid);
+ int freezeInfo = mFreezer.getBinderFreezeInfo(pid);
if ((freezeInfo & SYNC_RECEIVED_WHILE_FROZEN) != 0) {
Slog.d(TAG_AM, "pid " + pid + " " + app.processName
@@ -1553,7 +1482,7 @@
}
if (processKilled) {
- return;
+ return false;
}
if (!processFreezableChangeReported) {
reportProcessFreezableChangedLocked(app);
@@ -1562,19 +1491,19 @@
long freezeTime = opt.getFreezeUnfreezeTime();
try {
- freezeBinder(pid, false, FREEZE_BINDER_TIMEOUT_MS);
+ mFreezer.freezeBinder(pid, false, FREEZE_BINDER_TIMEOUT_MS);
} catch (RuntimeException e) {
Slog.e(TAG_AM, "Unable to unfreeze binder for " + pid + " " + app.processName
+ ". Killing it");
app.killLocked("Unable to unfreeze",
ApplicationExitInfo.REASON_FREEZER,
ApplicationExitInfo.SUBREASON_FREEZER_BINDER_IOCTL, true);
- return;
+ return false;
}
try {
traceAppFreeze(app.processName, pid, reason);
- Process.setProcessFrozen(pid, app.uid, false);
+ mFreezer.setProcessFrozen(pid, app.uid, false);
opt.setFreezeUnfreezeTime(SystemClock.uptimeMillis());
opt.setFrozen(false);
@@ -1592,14 +1521,25 @@
pid,
(int) Math.min(opt.getFreezeUnfreezeTime() - freezeTime, Integer.MAX_VALUE),
new Pair<ProcessRecord, Integer>(app, reason)));
+ return true;
+ }
+ return false;
+ }
+
+ @GuardedBy({"mAm", "mProcLock"})
+ void unfreezeAppLSP(ProcessRecord app, @UnfreezeReason int reason, boolean force) {
+ final boolean shouldDispatch;
+ synchronized (mFreezerLock) {
+ shouldDispatch = unfreezeAppInternalLSP(app, reason, force);
+ }
+ if (shouldDispatch) {
+ app.mOptRecord.dispatchUnfrozenEvent();
}
}
@GuardedBy({"mAm", "mProcLock"})
void unfreezeAppLSP(ProcessRecord app, @UnfreezeReason int reason) {
- synchronized (mFreezerLock) {
- unfreezeAppInternalLSP(app, reason, false);
- }
+ unfreezeAppLSP(app, reason, false);
}
/**
@@ -1610,14 +1550,15 @@
* @param pid pid of the process to be unfrozen
*/
void unfreezeProcess(int pid, @OomAdjReason int reason) {
+ final ProcessRecord app;
synchronized (mFreezerLock) {
- ProcessRecord app = mFrozenProcesses.get(pid);
+ app = mFrozenProcesses.get(pid);
if (app == null) {
return;
}
Slog.d(TAG_AM, "quick sync unfreeze " + pid + " for " + reason);
try {
- freezeBinder(pid, false, FREEZE_BINDER_TIMEOUT_MS);
+ mFreezer.freezeBinder(pid, false, FREEZE_BINDER_TIMEOUT_MS);
} catch (RuntimeException e) {
Slog.e(TAG_AM, "Unable to quick unfreeze binder for " + pid);
return;
@@ -1625,11 +1566,12 @@
try {
traceAppFreeze(app.processName, pid, reason);
- Process.setProcessFrozen(pid, app.uid, false);
+ mFreezer.setProcessFrozen(pid, app.uid, false);
} catch (Exception e) {
Slog.e(TAG_AM, "Unable to quick unfreeze " + pid);
}
}
+ app.mOptRecord.dispatchUnfrozenEvent();
}
/**
@@ -2394,7 +2336,7 @@
// Freeze binder interface before the process, to flush any
// transactions that might be pending.
try {
- if (freezeBinder(pid, true, FREEZE_BINDER_TIMEOUT_MS) != 0) {
+ if (mFreezer.freezeBinder(pid, true, FREEZE_BINDER_TIMEOUT_MS) != 0) {
handleBinderFreezerFailure(proc, "outstanding txns");
return;
}
@@ -2413,7 +2355,7 @@
try {
traceAppFreeze(proc.processName, pid, -1);
- Process.setProcessFrozen(pid, proc.uid, true);
+ mFreezer.setProcessFrozen(pid, proc.uid, true);
opt.setFreezeUnfreezeTime(SystemClock.uptimeMillis());
opt.setFrozen(true);
opt.setHasCollectedFrozenPSS(false);
@@ -2452,7 +2394,7 @@
try {
// post-check to prevent races
- int freezeInfo = getBinderFreezeInfo(pid);
+ int freezeInfo = mFreezer.getBinderFreezeInfo(pid);
if ((freezeInfo & TXNS_PENDING_WHILE_FROZEN) != 0) {
synchronized (mProcLock) {
@@ -2470,6 +2412,7 @@
}
});
}
+ opt.dispatchFrozenEvent();
}
private void reportUnfreeze(ProcessRecord app, int pid, int frozenDuration,
@@ -2620,6 +2563,22 @@
}
/**
+ * Freeze or unfreeze a process. This should only be used for testing.
+ */
+ @VisibleForTesting
+ void forceFreezeForTest(ProcessRecord proc, boolean freeze) {
+ synchronized (mAm) {
+ synchronized (mProcLock) {
+ if (freeze) {
+ forceFreezeAppAsyncLSP(proc);
+ } else {
+ unfreezeAppLSP(proc, UNFREEZE_REASON_NONE, true);
+ }
+ }
+ }
+ }
+
+ /**
* Sending binder transactions to frozen apps most likely indicates there's a bug. Log it and
* kill the frozen apps if they 1) receive sync binder transactions while frozen, or 2) miss
* async binder transactions due to kernel binder buffer running out.
@@ -2660,7 +2619,7 @@
for (int i = 0; i < pids.size(); i++) {
int current = pids.get(i);
try {
- int freezeInfo = getBinderFreezeInfo(current);
+ int freezeInfo = mFreezer.getBinderFreezeInfo(current);
if ((freezeInfo & SYNC_RECEIVED_WHILE_FROZEN) != 0) {
killProcess(current, "Sync transaction while frozen",
@@ -2716,4 +2675,12 @@
exception -> Slog.e(TAG_AM, "Unable to parse binderfs stats"));
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
+
+ /**
+ * Register a callback to notify when a process's frozen state changes.
+ */
+ public void addFrozenProcessListener(ProcessRecord app, Executor executor,
+ FrozenProcessListener listener) {
+ app.mOptRecord.addFrozenProcessListener(executor, listener);
+ }
}
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index afb7bb4..1314521 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -1806,10 +1806,12 @@
ActivityManagerService.WAIT_FOR_CONTENT_PROVIDER_TIMEOUT_MSG, cpr);
}
final int userId = UserHandle.getUserId(cpr.uid);
+ boolean removed = false;
// Don't remove from provider map if it doesn't match
// could be a new content provider is starting
if (mProviderMap.getProviderByClass(cpr.name, userId) == cpr) {
mProviderMap.removeProviderByClass(cpr.name, userId);
+ removed = true;
}
String[] names = cpr.info.authority.split(";");
for (int j = 0; j < names.length; j++) {
@@ -1817,8 +1819,12 @@
// could be a new content provider is starting
if (mProviderMap.getProviderByName(names[j], userId) == cpr) {
mProviderMap.removeProviderByName(names[j], userId);
+ removed = true;
}
}
+ if (removed && cpr.proc != null) {
+ cpr.proc.mProviders.removeProvider(cpr.info.name);
+ }
}
for (int i = cpr.connections.size() - 1; i >= 0; i--) {
diff --git a/services/core/java/com/android/server/am/Freezer.java b/services/core/java/com/android/server/am/Freezer.java
new file mode 100644
index 0000000..3b3cf55
--- /dev/null
+++ b/services/core/java/com/android/server/am/Freezer.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+
+import android.os.Process;
+
+/**
+ * A collection of interfaces to manage the freezer. All access to the freezer goes through an
+ * instance of this class. The class can be overridden for testing.
+ *
+ * Methods may be called without external synchronization. Multiple instances of this class can be
+ * used concurrently.
+ */
+class Freezer {
+
+ /**
+ * Freeze or unfreeze the specified process.
+ *
+ * @param pid Identifier of the process to freeze or unfreeze.
+ * @param uid Identifier of the user the process is running under.
+ * @param frozen Specify whether to free (true) or unfreeze (false).
+ */
+ public void setProcessFrozen(int pid, int uid, boolean frozen) {
+ Process.setProcessFrozen(pid, uid, frozen);
+ }
+
+ /**
+ * Informs binder that a process is about to be frozen. If freezer is enabled on a process via
+ * this method, this method will synchronously dispatch all pending transactions to the
+ * specified pid. This method will not add significant latencies when unfreezing.
+ * After freezing binder calls, binder will block all transaction to the frozen pid, and return
+ * an error to the sending process.
+ *
+ * @param pid the target pid for which binder transactions are to be frozen
+ * @param freeze specifies whether to flush transactions and then freeze (true) or unfreeze
+ * binder for the specified pid.
+ * @param timeoutMs the timeout in milliseconds to wait for the binder interface to freeze
+ * before giving up.
+ *
+ * @throws RuntimeException in case a flush/freeze operation could not complete successfully.
+ * @return 0 if success, or -EAGAIN indicating there's pending transaction.
+ */
+ public int freezeBinder(int pid, boolean freeze, int timeoutMs) {
+ return nativeFreezeBinder(pid, freeze, timeoutMs);
+ }
+
+ /**
+ * Retrieves binder freeze info about a process.
+ * @param pid the pid for which binder freeze info is to be retrieved.
+ *
+ * @throws RuntimeException if the operation could not complete successfully.
+ * @return a bit field reporting the binder freeze info for the process.
+ */
+ public int getBinderFreezeInfo(int pid) {
+ return nativeGetBinderFreezeInfo(pid);
+ }
+
+ /**
+ * Determines whether the freezer is supported by this system.
+ * @return true if the freezer is supported.
+ */
+ public boolean isFreezerSupported() {
+ return nativeIsFreezerSupported();
+ }
+
+ // Native methods
+
+ /**
+ * Informs binder that a process is about to be frozen. If freezer is enabled on a process via
+ * this method, this method will synchronously dispatch all pending transactions to the
+ * specified pid. This method will not add significant latencies when unfreezing.
+ * After freezing binder calls, binder will block all transaction to the frozen pid, and return
+ * an error to the sending process.
+ *
+ * @param pid the target pid for which binder transactions are to be frozen
+ * @param freeze specifies whether to flush transactions and then freeze (true) or unfreeze
+ * binder for the specified pid.
+ * @param timeoutMs the timeout in milliseconds to wait for the binder interface to freeze
+ * before giving up.
+ *
+ * @throws RuntimeException in case a flush/freeze operation could not complete successfully.
+ * @return 0 if success, or -EAGAIN indicating there's pending transaction.
+ */
+ private static native int nativeFreezeBinder(int pid, boolean freeze, int timeoutMs);
+
+ /**
+ * Retrieves binder freeze info about a process.
+ * @param pid the pid for which binder freeze info is to be retrieved.
+ *
+ * @throws RuntimeException if the operation could not complete successfully.
+ * @return a bit field reporting the binder freeze info for the process.
+ */
+ private static native int nativeGetBinderFreezeInfo(int pid);
+
+ /**
+ * Return 0 if the freezer is supported on this platform and -1 otherwise.
+ */
+ private static native boolean nativeIsFreezerSupported();
+}
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index b517631..d6f04db 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -39,6 +39,7 @@
per-file ContentProviderHelper.java = varunshah@google.com, omakoto@google.com, jsharkey@google.com, yamasani@google.com
per-file CachedAppOptimizer.java = file:/PERFORMANCE_OWNERS
+per-file Freezer.java = file:/PERFORMANCE_OWNERS
# Multiuser
per-file User* = file:/MULTIUSER_OWNERS
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 8eef71e..6857b6b 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -19,9 +19,11 @@
import static android.app.ActivityManager.PROCESS_STATE_TOP;
import static android.app.ActivityManager.START_SUCCESS;
import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED;
+import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS;
import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_COMPAT;
import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED;
import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED;
+import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE;
import static android.os.Process.ROOT_UID;
import static android.os.Process.SYSTEM_UID;
@@ -367,17 +369,6 @@
}
/**
- * Return true if the activity options allows PendingIntent to use caller's BAL permission.
- */
- public static boolean isPendingIntentBalAllowedByPermission(
- @Nullable ActivityOptions activityOptions) {
- if (activityOptions == null) {
- return false;
- }
- return activityOptions.isPendingIntentBackgroundActivityLaunchAllowedByPermission();
- }
-
- /**
* Return the {@link BackgroundStartPrivileges} the activity options grant the PendingIntent to
* use caller's BAL permission.
*/
@@ -404,6 +395,8 @@
return BackgroundStartPrivileges.NONE;
case MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED:
return getDefaultBackgroundStartPrivileges(callingUid, callingPackage);
+ case MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS:
+ case MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE:
case MODE_BACKGROUND_ACTIVITY_START_ALLOWED:
case MODE_BACKGROUND_ACTIVITY_START_COMPAT:
default:
diff --git a/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java b/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
index 53643b8..57a5e3f 100644
--- a/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
+++ b/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
@@ -19,6 +19,8 @@
import android.annotation.IntDef;
import android.annotation.UptimeMillisLong;
import android.app.ActivityManagerInternal.OomAdjReason;
+import android.app.ActivityManagerInternal.FrozenProcessListener;
+import android.util.Pair;
import android.util.TimeUtils;
import com.android.internal.annotations.GuardedBy;
@@ -29,6 +31,8 @@
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Executor;
/**
* The state info of app when it's cached, used by the optimizer.
@@ -165,6 +169,12 @@
@GuardedBy("mProcLock")
private long mLastUsedTimeout;
+ /**
+ * The list of callbacks for this process whenever it is frozen or unfrozen.
+ */
+ final CopyOnWriteArrayList<Pair<Executor, FrozenProcessListener>> mFrozenProcessListeners =
+ new CopyOnWriteArrayList<>();
+
@GuardedBy("mProcLock")
long getLastCompactTime() {
return mLastCompactTime;
@@ -386,6 +396,22 @@
mFreezeExempt = exempt;
}
+ void addFrozenProcessListener(Executor executor, FrozenProcessListener listener) {
+ mFrozenProcessListeners.add(new Pair<Executor, FrozenProcessListener>(executor, listener));
+ }
+
+ void dispatchFrozenEvent() {
+ mFrozenProcessListeners.forEach((pair) -> {
+ pair.first.execute(() -> pair.second.onProcessFrozen(mApp.mPid));
+ });
+ }
+
+ void dispatchUnfrozenEvent() {
+ mFrozenProcessListeners.forEach((pair) -> {
+ pair.first.execute(() -> pair.second.onProcessUnfrozen(mApp.mPid));
+ });
+ }
+
ProcessCachedOptimizerRecord(ProcessRecord app) {
mApp = app;
mProcLock = app.mService.mProcLock;
@@ -409,6 +435,10 @@
pw.print(" " + IS_FROZEN + "="); pw.println(mFrozen);
pw.print(prefix); pw.print("earliestFreezableTimeMs=");
TimeUtils.formatDuration(mEarliestFreezableTimeMillis, nowUptime, pw);
+ if (!mFrozenProcessListeners.isEmpty()) {
+ pw.print(" mFrozenProcessListeners=");
+ mFrozenProcessListeners.forEach((pair) -> pw.print(pair.second + ", "));
+ }
pw.println();
}
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 726e827..bb0c24b 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -3005,7 +3005,7 @@
return freezePackageCgroup(packageUID, false);
}
- private static void freezeBinderAndPackageCgroup(List<Pair<ProcessRecord, Boolean>> procs,
+ private void freezeBinderAndPackageCgroup(List<Pair<ProcessRecord, Boolean>> procs,
int packageUID) {
// Freeze all binder processes under the target UID (whose cgroup is about to be frozen).
// Since we're going to kill these, we don't need to unfreze them later.
@@ -3019,7 +3019,7 @@
try {
int rc;
do {
- rc = CachedAppOptimizer.freezeBinder(pid, true, 10 /* timeout_ms */);
+ rc = mService.getFreezer().freezeBinder(pid, true, 10 /* timeout_ms */);
} while (rc == -EAGAIN && nRetries++ < 1);
if (rc != 0) Slog.e(TAG, "Unable to freeze binder for " + pid + ": " + rc);
} catch (RuntimeException e) {
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 92553b9..ca907c5 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -2799,6 +2799,10 @@
return;
}
final SettingsAdapter settingsAdapter = mAudioService.getSettings();
+ if (settingsAdapter == null) {
+ Log.e(TAG, "No settings adapter when saving AdiDeviceState: " + deviceSettings);
+ return;
+ }
try {
boolean res = settingsAdapter.putSecureStringForUser(mAudioService.getContentResolver(),
Settings.Secure.AUDIO_DEVICE_INVENTORY,
@@ -2814,6 +2818,12 @@
private String readDeviceSettings() {
final SettingsAdapter settingsAdapter = mAudioService.getSettings();
final ContentResolver contentResolver = mAudioService.getContentResolver();
+ if (settingsAdapter == null || contentResolver == null) {
+ // should not happen, throw Exception for stack trace
+ Log.e(TAG, "No settings adapter or content resolver to read device settings",
+ new Exception("readDeviceSettings_NPE"));
+ return "";
+ }
return settingsAdapter.getSecureStringForUser(contentResolver,
Settings.Secure.AUDIO_DEVICE_INVENTORY, UserHandle.USER_CURRENT);
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index ac43e86..53b04df 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -2032,8 +2032,11 @@
synchronized (mCachedAbsVolDrivingStreamsLock) {
mCachedAbsVolDrivingStreams.forEach((dev, stream) -> {
- mAudioSystem.setDeviceAbsoluteVolumeEnabled(dev, /*address=*/"", /*enabled=*/true,
- stream);
+ boolean enabled = true;
+ if (dev == AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
+ enabled = mAvrcpAbsVolSupported;
+ }
+ mAudioSystem.setDeviceAbsoluteVolumeEnabled(dev, /*address=*/"", enabled, stream);
});
}
@@ -4831,6 +4834,20 @@
private void onUpdateContextualVolumes() {
final int streamType = getBluetoothContextualVolumeStream();
+ synchronized (mCachedAbsVolDrivingStreamsLock) {
+ mCachedAbsVolDrivingStreams.replaceAll((absDev, stream) -> {
+ boolean enabled = true;
+ if (absDev == AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
+ enabled = mAvrcpAbsVolSupported;
+ }
+ if (stream != streamType) {
+ mAudioSystem.setDeviceAbsoluteVolumeEnabled(absDev, /*address=*/"",
+ enabled, streamType);
+ }
+ return streamType;
+ });
+ }
+
final Set<Integer> deviceTypes = getDeviceSetForStreamDirect(streamType);
final Set<Integer> absVolumeMultiModeCaseDevices =
AudioSystem.intersectionAudioDeviceTypes(
@@ -6450,17 +6467,6 @@
// change of mode may require volume to be re-applied on some devices
onUpdateContextualVolumes();
- synchronized (mCachedAbsVolDrivingStreamsLock) {
- mCachedAbsVolDrivingStreams.replaceAll((absDev, stream) -> {
- int streamToDriveAbs = getBluetoothContextualVolumeStream();
- if (stream != streamToDriveAbs) {
- mAudioSystem.setDeviceAbsoluteVolumeEnabled(absDev, /*address=*/
- "", /*enabled*/true, streamToDriveAbs);
- }
- return streamToDriveAbs;
- });
- }
-
// 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.postSetModeOwner(mode, pid, uid);
diff --git a/services/core/java/com/android/server/biometrics/biometrics.aconfig b/services/core/java/com/android/server/biometrics/biometrics.aconfig
index 15c8850..b2e95aa 100644
--- a/services/core/java/com/android/server/biometrics/biometrics.aconfig
+++ b/services/core/java/com/android/server/biometrics/biometrics.aconfig
@@ -16,8 +16,11 @@
}
flag {
- name: "notify_fingerprint_loe"
+ name: "notify_fingerprints_loe"
namespace: "biometrics_framework"
description: "This flag controls whether a notification should be sent to notify user when loss of enrollment happens"
bug: "351036558"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
index 3b6aeef..77e27ba 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
@@ -108,7 +108,7 @@
}
if (mBiometricUtils.hasValidBiometricUserState(getContext(), getTargetUserId())
- && Flags.notifyFingerprintLoe()) {
+ && Flags.notifyFingerprintsLoe()) {
handleInvalidBiometricState();
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index ef7abdd..6cce722 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -227,6 +227,9 @@
onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
mCallback.onClientFinished(this, false /* success */);
}
+ } else {
+ Slog.e(TAG, "Cancellation signal is null");
+ mCallback.onClientFinished(this, false /* success */);
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index d04afdb..dee4b4f 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -359,7 +359,8 @@
mCallback.onClientFinished(this, false /* success */);
}
} else {
- Slog.e(TAG, "cancellation signal was null");
+ Slog.e(TAG, "Cancellation signal was null");
+ mCallback.onClientFinished(this, false /* success */);
}
}
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 5b23364c..969a684 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -2158,8 +2158,12 @@
}
if (mBound) {
mBound = false;
- mLogger.log("unbindService for ", this);
- mContext.unbindService(this);
+ try {
+ mLogger.log("unbindService for ", this);
+ mContext.unbindService(this);
+ } catch (NoSuchElementException e) {
+ Slog.wtf(TAG, "Failed to unlink active sync adapter on close()", e);
+ }
try {
mBatteryStats.noteSyncFinish(mEventName, mSyncAdapterUid);
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index 619aecf..38e6d82 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -50,8 +50,7 @@
import android.hardware.devicestate.DeviceStateManagerInternal;
import android.hardware.devicestate.IDeviceStateManager;
import android.hardware.devicestate.IDeviceStateManagerCallback;
-import android.hardware.devicestate.feature.flags.FeatureFlags;
-import android.hardware.devicestate.feature.flags.FeatureFlagsImpl;
+import android.hardware.devicestate.feature.flags.Flags;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -190,9 +189,6 @@
@Nullable
private OverrideRequest mRearDisplayPendingOverrideRequest;
- @NonNull
- private final FeatureFlags mFlags;
-
@VisibleForTesting
interface SystemPropertySetter {
void setDebugTracingDeviceStateProperty(String value);
@@ -253,7 +249,6 @@
@NonNull SystemPropertySetter systemPropertySetter) {
super(context);
mSystemPropertySetter = systemPropertySetter;
- mFlags = new FeatureFlagsImpl();
// We use the DisplayThread because this service indirectly drives
// display (on/off) and window (position) events through its callbacks.
DisplayThread displayThread = DisplayThread.get();
@@ -279,7 +274,7 @@
publishBinderService(Context.DEVICE_STATE_SERVICE, mBinderService);
publishLocalService(DeviceStateManagerInternal.class, new LocalService());
- if (!mFlags.deviceStatePropertyMigration()) {
+ if (!Flags.deviceStatePropertyMigration()) {
synchronized (mLock) {
readStatesAvailableForRequestFromApps();
mFoldedDeviceStates = readFoldedStates();
@@ -848,7 +843,7 @@
OverrideRequest request = new OverrideRequest(token, callingPid, callingUid,
deviceState.get(), flags, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
- if (mFlags.deviceStatePropertyMigration()) {
+ if (Flags.deviceStatePropertyMigration()) {
// If we don't have the CONTROL_DEVICE_STATE permission, we want to show the overlay
if (!hasControlDeviceStatePermission && deviceState.get().hasProperty(
PROPERTY_FEATURE_REAR_DISPLAY)) {
@@ -988,16 +983,16 @@
* @param callingPid Process ID that is requesting this state change
* @param state state that is being requested.
*/
- private void assertCanRequestDeviceState(int callingPid, int callingUid, int state) {
+ private void enforceRequestDeviceStatePermitted(int callingPid, int callingUid, int state) {
final boolean isTopApp = isTopApp(callingPid);
final boolean isForegroundApp = isForegroundApp(callingPid, callingUid);
final boolean isStateAvailableForAppRequests = isStateAvailableForAppRequests(state);
- final boolean canRequestState = isTopApp
+ final boolean isAllowedToRequestState = isTopApp
&& isForegroundApp
&& isStateAvailableForAppRequests;
- if (!canRequestState) {
+ if (!isAllowedToRequestState) {
getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
"Permission required to request device state, "
+ "or the call must come from the top app "
@@ -1006,19 +1001,29 @@
}
/**
- * Checks if the process can control the device state. If the calling process ID is
- * not the top app, then check if this process holds the CONTROL_DEVICE_STATE permission.
+ * Checks if the process can cancel a device state request. If the calling process ID is not
+ * both the top app and foregrounded nor does the process ID and userID match the IDs that made
+ * the device state request, then check if this process holds the CONTROL_DEVICE_STATE
+ * permission.
*
* @param callingPid Process ID that is requesting this state change
* @param callingUid UID that is requesting this state change
*/
- private void assertCanControlDeviceState(int callingPid, int callingUid) {
+ private void enforceCancelDeviceStatePermitted(int callingPid, int callingUid) {
final boolean isTopApp = isTopApp(callingPid);
final boolean isForegroundApp = isForegroundApp(callingPid, callingUid);
- final boolean canControlState = isTopApp && isForegroundApp;
+ boolean isAllowedToControlState = isTopApp && isForegroundApp;
- if (!canControlState) {
+ if (Flags.deviceStateRequesterCancelState()) {
+ synchronized (mLock) {
+ isAllowedToControlState =
+ isAllowedToControlState || doCallingIdsMatchOverrideRequestIdsLocked(
+ callingPid, callingUid);
+ }
+ }
+
+ if (!isAllowedToControlState) {
getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
"Permission required to request device state, "
+ "or the call must come from the top app.");
@@ -1052,9 +1057,19 @@
return topApp != null && topApp.getPid() == callingPid;
}
+ /**
+ * Returns if the provided {@code callingPid} and {@code callingUid} match the same id's that
+ * requested the current device state override.
+ */
+ @GuardedBy("mLock")
+ private boolean doCallingIdsMatchOverrideRequestIdsLocked(int callingPid, int callingUid) {
+ OverrideRequest request = mActiveOverride.orElse(null);
+ return request != null && request.getPid() == callingPid && request.getUid() == callingUid;
+ }
+
private boolean isStateAvailableForAppRequests(int state) {
synchronized (mLock) {
- if (mFlags.deviceStatePropertyMigration()) {
+ if (Flags.deviceStatePropertyMigration()) {
Optional<DeviceState> deviceState = getStateLocked(state);
return deviceState.isPresent() && deviceState.get().hasProperty(
PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST);
@@ -1122,7 +1137,7 @@
*/
@GuardedBy("mLock")
private boolean isDeviceOpeningLocked(int newBaseState) {
- if (mFlags.deviceStatePropertyMigration()) {
+ if (Flags.deviceStatePropertyMigration()) {
final DeviceState currentBaseState = mBaseState.orElse(INVALID_DEVICE_STATE);
final DeviceState newDeviceBaseState = getStateLocked(newBaseState).orElse(
INVALID_DEVICE_STATE);
@@ -1293,7 +1308,7 @@
// Allow top processes to request a device state change
// If the calling process ID is not the top app, then we check if this process
// holds a permission to CONTROL_DEVICE_STATE
- assertCanRequestDeviceState(callingPid, callingUid, state);
+ enforceRequestDeviceStatePermitted(callingPid, callingUid, state);
if (token == null) {
throw new IllegalArgumentException("Request token must not be null.");
@@ -1318,7 +1333,7 @@
// Allow top processes to cancel a device state change
// If the calling process ID is not the top app, then we check if this process
// holds a permission to CONTROL_DEVICE_STATE
- assertCanControlDeviceState(callingPid, callingUid);
+ enforceCancelDeviceStatePermitted(callingPid, callingUid);
final long callingIdentity = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 7b5cff7..226bdf5 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -579,6 +579,14 @@
return mCurrentBrightnessMapper.getMode();
}
+ /**
+ * @return The preset for this mapping strategy. Presets are used on devices that allow users
+ * to choose from a set of predefined options in display auto-brightness settings.
+ */
+ public int getPreset() {
+ return mCurrentBrightnessMapper.getPreset();
+ }
+
public boolean isInIdleMode() {
return mCurrentBrightnessMapper.getMode() == AUTO_BRIGHTNESS_MODE_IDLE;
}
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index 8405e0a..b0507fb 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -140,10 +140,10 @@
builder.setShortTermModelLowerLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO);
builder.setShortTermModelUpperLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO);
return new PhysicalMappingStrategy(builder.build(), nitsRange, brightnessRange,
- autoBrightnessAdjustmentMaxGamma, mode, displayWhiteBalanceController);
+ autoBrightnessAdjustmentMaxGamma, mode, preset, displayWhiteBalanceController);
} else if (isValidMapping(luxLevels, brightnessLevels)) {
return new SimpleMappingStrategy(luxLevels, brightnessLevels,
- autoBrightnessAdjustmentMaxGamma, shortTermModelTimeout, mode);
+ autoBrightnessAdjustmentMaxGamma, shortTermModelTimeout, mode, preset);
} else {
return null;
}
@@ -394,6 +394,12 @@
abstract int getMode();
/**
+ * @return The preset for this mapping strategy. Presets are used on devices that allow users
+ * to choose from a set of predefined options in display auto-brightness settings.
+ */
+ abstract int getPreset();
+
+ /**
* Check if the short term model should be reset given the anchor lux the last
* brightness change was made at and the current ambient lux.
*/
@@ -598,6 +604,8 @@
@AutomaticBrightnessController.AutomaticBrightnessMode
private final int mMode;
+ private final int mPreset;
+
private Spline mSpline;
private float mMaxGamma;
private float mAutoBrightnessAdjustment;
@@ -606,7 +614,8 @@
private long mShortTermModelTimeout;
private SimpleMappingStrategy(float[] lux, float[] brightness, float maxGamma,
- long timeout, @AutomaticBrightnessController.AutomaticBrightnessMode int mode) {
+ long timeout, @AutomaticBrightnessController.AutomaticBrightnessMode int mode,
+ int preset) {
Preconditions.checkArgument(lux.length != 0 && brightness.length != 0,
"Lux and brightness arrays must not be empty!");
Preconditions.checkArgument(lux.length == brightness.length,
@@ -633,6 +642,7 @@
computeSpline();
mShortTermModelTimeout = timeout;
mMode = mode;
+ mPreset = preset;
}
@Override
@@ -766,6 +776,11 @@
}
@Override
+ int getPreset() {
+ return mPreset;
+ }
+
+ @Override
float getUserLux() {
return mUserLux;
}
@@ -837,6 +852,8 @@
@AutomaticBrightnessController.AutomaticBrightnessMode
private final int mMode;
+ private final int mPreset;
+
// Previous short-term models and the times that they were computed stored for debugging
// purposes
private List<Spline> mPreviousBrightnessSplines = new ArrayList<>();
@@ -846,7 +863,7 @@
public PhysicalMappingStrategy(BrightnessConfiguration config, float[] nits,
float[] brightness, float maxGamma,
- @AutomaticBrightnessController.AutomaticBrightnessMode int mode,
+ @AutomaticBrightnessController.AutomaticBrightnessMode int mode, int preset,
@Nullable DisplayWhiteBalanceController displayWhiteBalanceController) {
Preconditions.checkArgument(nits.length != 0 && brightness.length != 0,
@@ -860,6 +877,7 @@
PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, "brightness");
mMode = mode;
+ mPreset = preset;
mMaxGamma = maxGamma;
mAutoBrightnessAdjustment = 0;
mUserLux = INVALID_LUX;
@@ -1073,6 +1091,11 @@
}
@Override
+ int getPreset() {
+ return mPreset;
+ }
+
+ @Override
float getUserLux() {
return mUserLux;
}
diff --git a/services/core/java/com/android/server/display/BrightnessRangeController.java b/services/core/java/com/android/server/display/BrightnessRangeController.java
index 515e704..8a3e392 100644
--- a/services/core/java/com/android/server/display/BrightnessRangeController.java
+++ b/services/core/java/com/android/server/display/BrightnessRangeController.java
@@ -60,7 +60,7 @@
mModeChangeCallback = modeChangeCallback;
mHdrClamper = hdrClamper;
mNormalBrightnessModeController = normalBrightnessModeController;
- mUseHdrClamper = flags.isHdrClamperEnabled();
+ mUseHdrClamper = flags.isHdrClamperEnabled() && !flags.useNewHdrBrightnessModifier();
mUseNbmController = flags.isNbmControllerEnabled();
if (mUseNbmController) {
mNormalBrightnessModeController.resetNbmData(
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index ed6ed60..cc115f1 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -588,22 +588,43 @@
* <minorVersion>0</minorVersion>
* </usiVersion>
* <evenDimmer enabled="true">
- * <transitionPoint>0.1</transitionPoint>
- *
- * <nits>0.2</nits>
- * <nits>2.0</nits>
- * <nits>500.0</nits>
- * <nits>1000.0</nits>
- *
- * <backlight>0</backlight>
- * <backlight>0.0001</backlight>
- * <backlight>0.5</backlight>
- * <backlight>1.0</backlight>
- *
- * <brightness>0</brightness>
- * <brightness>0.1</brightness>
- * <brightness>0.5</brightness>
- * <brightness>1.0</brightness>
+ * <transitionPoint>0.1</transitionPoint>
+ * <brightnessMapping>
+ * <brightnessPoint>
+ * <nits>0.2</nits>
+ * <backlight>0</backlight>
+ * <brightness>0</brightness>
+ * </brightnessPoint>
+ * <brightnessPoint>
+ * <nits>2.0</nits>
+ * <backlight>0.01</backlight>
+ * <brightness>0.002</brightness>
+ * </brightnessPoint>
+ * <brightnessPoint>
+ * <nits>500.0</nits>
+ * <backlight>0.5</backlight>
+ * <brightness>0.5</brightness>
+ * </brightnessPoint>
+ * <brightnessPoint>
+ * <nits>1000</nits>
+ * <backlight>1.0</backlight>
+ * <brightness>1.0</brightness>
+ * </brightnessPoint>
+ * </brightnessMapping>
+ * <luxToMinimumNitsMap>
+ * <point>
+ * <value>10</value>
+ * <nits>0.3</nits>
+ * </point>
+ * <point>
+ * <value>50</value>
+ * <nits>0.7</nits>
+ * </point>
+ * <point>
+ * <value>100</value>
+ * <nits>1.0</nits>
+ * </point>
+ * </luxToMinimumNitsMap>
* </evenDimmer>
* <screenBrightnessCapForWearBedtimeMode>0.1</screenBrightnessCapForWearBedtimeMode>
* <idleScreenRefreshRateTimeout>
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 2cec869..9e905ab 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -722,6 +722,7 @@
if (userSwitching) {
mCurrentUserId = newUserId;
}
+ mDisplayModeDirector.onSwitchUser();
mLogicalDisplayMapper.forEachLocked(logicalDisplay -> {
if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) {
return;
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 8b21d98..8bb33dd 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -17,6 +17,7 @@
package com.android.server.display;
import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE;
+import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_OFF;
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT;
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE;
@@ -702,6 +703,17 @@
private void handleOnSwitchUser(@UserIdInt int newUserId, int userSerial, float newBrightness) {
Slog.i(mTag, "Switching user newUserId=" + newUserId + " userSerial=" + userSerial
+ " newBrightness=" + newBrightness);
+
+ if (mAutomaticBrightnessController != null) {
+ int autoBrightnessPreset = Settings.System.getIntForUser(mContext.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS_FOR_ALS,
+ Settings.System.SCREEN_BRIGHTNESS_AUTOMATIC_NORMAL,
+ UserHandle.USER_CURRENT);
+ if (autoBrightnessPreset != mAutomaticBrightnessController.getPreset()) {
+ setUpAutoBrightness(mContext, mHandler);
+ }
+ }
+
handleBrightnessModeChange();
if (mBrightnessTracker != null) {
mBrightnessTracker.onSwitchUser(newUserId);
@@ -714,6 +726,7 @@
if (mAutomaticBrightnessController != null) {
mAutomaticBrightnessController.resetShortTermModel();
}
+ mBrightnessClamperController.onUserSwitch();
sendUpdatePowerState();
}
@@ -1009,7 +1022,7 @@
if (mFlags.areAutoBrightnessModesEnabled()) {
mContext.getContentResolver().registerContentObserver(
Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_ALS),
- /* notifyForDescendants= */ false, mSettingsObserver, UserHandle.USER_CURRENT);
+ /* notifyForDescendants= */ false, mSettingsObserver, UserHandle.USER_ALL);
}
handleBrightnessModeChange();
}
@@ -1381,8 +1394,8 @@
if (mScreenOffBrightnessSensorController != null) {
mScreenOffBrightnessSensorController
.setLightSensorEnabled(displayBrightnessState.getShouldUseAutoBrightness()
- && mIsEnabled && (state == Display.STATE_OFF
- || (state == Display.STATE_DOZE && !allowAutoBrightnessWhileDozing))
+ && mIsEnabled && (mPowerRequest.policy == POLICY_OFF
+ || (mPowerRequest.policy == POLICY_DOZE && !allowAutoBrightnessWhileDozing))
&& mLeadDisplayId == Layout.NO_LEAD_DISPLAY);
}
}
diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
index c632e77..e157b05 100644
--- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
@@ -359,11 +359,11 @@
public void setUpAutoBrightness(AutomaticBrightnessController automaticBrightnessController,
SensorManager sensorManager,
DisplayDeviceConfig displayDeviceConfig, Handler handler,
- BrightnessMappingStrategy brightnessMappingStrategy, boolean isEnabled,
+ BrightnessMappingStrategy brightnessMappingStrategy, boolean isDisplayEnabled,
int leadDisplayId) {
setAutomaticBrightnessController(automaticBrightnessController);
setUpAutoBrightnessFallbackStrategy(sensorManager, displayDeviceConfig, handler,
- brightnessMappingStrategy, isEnabled, leadDisplayId);
+ brightnessMappingStrategy, isDisplayEnabled, leadDisplayId);
}
/**
@@ -534,14 +534,14 @@
private void setUpAutoBrightnessFallbackStrategy(SensorManager sensorManager,
DisplayDeviceConfig displayDeviceConfig, Handler handler,
- BrightnessMappingStrategy brightnessMappingStrategy, boolean isEnabled,
+ BrightnessMappingStrategy brightnessMappingStrategy, boolean isDisplayEnabled,
int leadDisplayId) {
AutoBrightnessFallbackStrategy autoBrightnessFallbackStrategy =
getAutoBrightnessFallbackStrategy();
if (autoBrightnessFallbackStrategy != null) {
autoBrightnessFallbackStrategy.setupAutoBrightnessFallbackSensor(
sensorManager, displayDeviceConfig, handler, brightnessMappingStrategy,
- isEnabled, leadDisplayId);
+ isDisplayEnabled, leadDisplayId);
}
}
diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java
index 9324fc1..59fffe7 100644
--- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java
+++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java
@@ -71,6 +71,7 @@
private final List<DisplayDeviceDataListener> mDisplayDeviceDataListeners = new ArrayList<>();
private final List<StatefulModifier> mStatefulModifiers = new ArrayList<>();
+ private final List<UserSwitchListener> mUserSwitchListeners = new ArrayList<>();
private ModifiersAggregatedState mModifiersAggregatedState = new ModifiersAggregatedState();
private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener;
@@ -127,6 +128,9 @@
if (m instanceof StatefulModifier s) {
mStatefulModifiers.add(s);
}
+ if (m instanceof UserSwitchListener l) {
+ mUserSwitchListeners.add(l);
+ }
});
mOnPropertiesChangedListener =
properties -> mClampers.forEach(BrightnessClamper::onDeviceConfigChanged);
@@ -209,6 +213,13 @@
}
/**
+ * Called when the user switches.
+ */
+ public void onUserSwitch() {
+ mUserSwitchListeners.forEach(listener -> listener.onSwitchUser());
+ }
+
+ /**
* Used to dump ClampersController state.
*/
public void dump(PrintWriter writer) {
@@ -336,7 +347,7 @@
data.mDisplayDeviceConfig));
}
if (flags.useNewHdrBrightnessModifier()) {
- modifiers.add(new HdrBrightnessModifier(handler, listener, data));
+ modifiers.add(new HdrBrightnessModifier(handler, context, listener, data));
}
return modifiers;
}
@@ -466,6 +477,13 @@
}
/**
+ * A clamper/modifier should implement this interface if it reads user-specific settings
+ */
+ interface UserSwitchListener {
+ void onSwitchUser();
+ }
+
+ /**
* StatefulModifiers contribute to AggregatedState, that is used to decide if brightness
* adjustement is needed
*/
diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessLowLuxModifier.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessLowLuxModifier.java
index 951980a..c3596c3 100644
--- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessLowLuxModifier.java
+++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessLowLuxModifier.java
@@ -41,7 +41,8 @@
* Class used to prevent the screen brightness dipping below a certain value, based on current
* lux conditions and user preferred minimum.
*/
-public class BrightnessLowLuxModifier extends BrightnessModifier {
+public class BrightnessLowLuxModifier extends BrightnessModifier implements
+ BrightnessClamperController.UserSwitchListener {
// To enable these logs, run:
// 'adb shell setprop persist.log.tag.BrightnessLowLuxModifier DEBUG && adb reboot'
@@ -81,10 +82,9 @@
*/
@VisibleForTesting
public void recalculateLowerBound() {
- int userId = UserHandle.USER_CURRENT;
float settingNitsLowerBound = Settings.Secure.getFloatForUser(
mContentResolver, Settings.Secure.EVEN_DIMMER_MIN_NITS,
- /* def= */ MIN_NITS_DEFAULT, userId);
+ /* def= */ MIN_NITS_DEFAULT, UserHandle.USER_CURRENT);
boolean isActive = isSettingEnabled()
&& mAmbientLux != BrightnessMappingStrategy.INVALID_LUX;
@@ -190,6 +190,11 @@
}
@Override
+ public void onSwitchUser() {
+ recalculateLowerBound();
+ }
+
+ @Override
public void dump(PrintWriter pw) {
pw.println("BrightnessLowLuxModifier:");
pw.println(" mIsActive=" + mIsActive);
@@ -221,10 +226,10 @@
super(handler);
mContentResolver.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.EVEN_DIMMER_MIN_NITS),
- false, this);
+ false, this, UserHandle.USER_ALL);
mContentResolver.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.EVEN_DIMMER_ACTIVATED),
- false, this);
+ false, this, UserHandle.USER_ALL);
}
@Override
diff --git a/services/core/java/com/android/server/display/brightness/clamper/HdrBrightnessModifier.java b/services/core/java/com/android/server/display/brightness/clamper/HdrBrightnessModifier.java
index 5e44cc3..4ab4336 100644
--- a/services/core/java/com/android/server/display/brightness/clamper/HdrBrightnessModifier.java
+++ b/services/core/java/com/android/server/display/brightness/clamper/HdrBrightnessModifier.java
@@ -21,16 +21,22 @@
import android.annotation.Nullable;
import android.annotation.SuppressLint;
+import android.content.Context;
+import android.database.ContentObserver;
import android.hardware.display.DisplayManagerInternal;
+import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
+import android.os.UserHandle;
+import android.provider.Settings;
import android.view.SurfaceControlHdrLayerInfoListener;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.DisplayDeviceConfig;
+import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.config.HdrBrightnessData;
import java.io.PrintWriter;
@@ -43,6 +49,11 @@
static final float DEFAULT_MAX_HDR_SDR_RATIO = 1.0f;
private static final float DEFAULT_HDR_LAYER_SIZE = -1.0f;
+ private final Uri mLowPowerModeSetting = Settings.Global.getUriFor(
+ Settings.Global.LOW_POWER_MODE);
+
+ private final ContentObserver mContentObserver;
+
private final SurfaceControlHdrLayerInfoListener mHdrListener =
new SurfaceControlHdrLayerInfoListener() {
@Override
@@ -51,7 +62,8 @@
boolean hdrLayerPresent = numberOfHdrLayers > 0;
mHandler.post(() -> HdrBrightnessModifier.this.onHdrInfoChanged(
hdrLayerPresent ? (float) (maxW * maxH) : DEFAULT_HDR_LAYER_SIZE,
- hdrLayerPresent ? maxDesiredHdrSdrRatio : DEFAULT_MAX_HDR_SDR_RATIO));
+ hdrLayerPresent ? Math.max(maxDesiredHdrSdrRatio,
+ DEFAULT_MAX_HDR_SDR_RATIO) : DEFAULT_MAX_HDR_SDR_RATIO));
}
};
@@ -61,6 +73,7 @@
private final Runnable mDebouncer;
private IBinder mRegisteredDisplayToken;
+ private boolean mContentObserverRegistered = false;
private DisplayDeviceConfig mDisplayDeviceConfig;
@Nullable
@@ -72,6 +85,8 @@
private float mAmbientLux = INVALID_LUX;
+ private boolean mLowPowerMode = false;
+
private Mode mMode = Mode.NO_HDR;
// The maximum brightness allowed for current lux
private float mMaxBrightness = PowerManager.BRIGHTNESS_MAX;
@@ -80,17 +95,17 @@
private float mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET;
private float mPendingTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET;
- HdrBrightnessModifier(Handler handler,
+ HdrBrightnessModifier(Handler handler, Context context,
BrightnessClamperController.ClamperChangeListener clamperChangeListener,
BrightnessClamperController.DisplayDeviceData displayData) {
- this(new Handler(handler.getLooper()), clamperChangeListener, new Injector(), displayData);
+ this(new Handler(handler.getLooper()), clamperChangeListener,
+ new Injector(context), displayData);
}
@VisibleForTesting
HdrBrightnessModifier(Handler handler,
BrightnessClamperController.ClamperChangeListener clamperChangeListener,
- Injector injector,
- BrightnessClamperController.DisplayDeviceData displayData) {
+ Injector injector, BrightnessClamperController.DisplayDeviceData displayData) {
mHandler = handler;
mClamperChangeListener = clamperChangeListener;
mInjector = injector;
@@ -99,7 +114,13 @@
mMaxBrightness = mPendingMaxBrightness;
mClamperChangeListener.onChanged();
};
- onDisplayChanged(displayData);
+ mContentObserver = new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ onLowPowerModeChange();
+ }
+ };
+ mHandler.post(() -> onDisplayChanged(displayData));
}
// Called in DisplayControllerHandler
@@ -120,6 +141,8 @@
stateBuilder.setHdrBrightness(hdrBrightness);
stateBuilder.setCustomAnimationRate(mTransitionRate);
+ stateBuilder.getBrightnessReason().addModifier(BrightnessReason.MODIFIER_HDR);
+
// transition rate applied, reset
mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET;
}
@@ -132,12 +155,14 @@
pw.println(" mMaxDesiredHdrRatio=" + mMaxDesiredHdrRatio);
pw.println(" mHdrLayerSize=" + mHdrLayerSize);
pw.println(" mAmbientLux=" + mAmbientLux);
+ pw.println(" mLowPowerMode=" + mLowPowerMode);
pw.println(" mMode=" + mMode);
pw.println(" mMaxBrightness=" + mMaxBrightness);
pw.println(" mPendingMaxBrightness=" + mPendingMaxBrightness);
pw.println(" mTransitionRate=" + mTransitionRate);
pw.println(" mPendingTransitionRate=" + mPendingTransitionRate);
pw.println(" mHdrListener registered=" + (mRegisteredDisplayToken != null));
+ pw.println(" mContentObserverRegistered=" + mContentObserverRegistered);
}
// Called in DisplayControllerHandler
@@ -168,10 +193,36 @@
}
}
+ // Called in DisplayControllerHandler
@Override
public void onDisplayChanged(BrightnessClamperController.DisplayDeviceData displayData) {
- mHandler.post(() -> onDisplayChanged(displayData.mDisplayToken, displayData.mWidth,
- displayData.mHeight, displayData.mDisplayDeviceConfig));
+ mDisplayDeviceConfig = displayData.mDisplayDeviceConfig;
+ mScreenSize = (float) displayData.mWidth * displayData.mHeight;
+ HdrBrightnessData data = mDisplayDeviceConfig.getHdrBrightnessData();
+ if (data == null) {
+ unregisterHdrListener();
+ } else {
+ registerHdrListener(displayData.mDisplayToken);
+ }
+ if (data == null || data.allowInLowPowerMode) {
+ unregisterContentObserver();
+ } else {
+ registerContentObserver();
+ }
+
+ Mode newMode = recalculateMode(data);
+ // mode changed, or mode was HDR and HdrBrightnessData changed
+ boolean needToNotifyChange = mMode != newMode
+ || (mMode != HdrBrightnessModifier.Mode.NO_HDR && data != mHdrBrightnessData);
+ mMode = newMode;
+ mHdrBrightnessData = data;
+ mMaxBrightness = findBrightnessLimit(mHdrBrightnessData, mAmbientLux);
+
+ if (needToNotifyChange) {
+ // data changed, reset custom transition rate
+ mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET;
+ mClamperChangeListener.onChanged();
+ }
}
// Called in DisplayControllerHandler, when any modifier state changes
@@ -215,49 +266,19 @@
}
// Called in DisplayControllerHandler
- private void onDisplayChanged(IBinder displayToken, int width, int height,
- DisplayDeviceConfig config) {
- mDisplayDeviceConfig = config;
- mScreenSize = (float) width * height;
- HdrBrightnessData data = config.getHdrBrightnessData();
- if (data == null) {
- unregisterHdrListener();
- } else {
- registerHdrListener(displayToken);
- }
- recalculate(data, mMaxDesiredHdrRatio);
- }
-
- // Called in DisplayControllerHandler
- private void recalculate(@Nullable HdrBrightnessData data, float maxDesiredHdrRatio) {
- Mode newMode = recalculateMode(data);
- // if HDR mode changed, notify changed
- boolean needToNotifyChange = mMode != newMode;
- // If HDR mode is active, we need to check if other HDR params are changed
- if (mMode != HdrBrightnessModifier.Mode.NO_HDR) {
- if (!BrightnessSynchronizer.floatEquals(mMaxDesiredHdrRatio, maxDesiredHdrRatio)
- || data != mHdrBrightnessData) {
- needToNotifyChange = true;
- }
- }
-
- mMode = newMode;
- mHdrBrightnessData = data;
- mMaxDesiredHdrRatio = maxDesiredHdrRatio;
-
- if (needToNotifyChange) {
- // data or hdr layer changed, reset custom transition rate
- mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET;
- mClamperChangeListener.onChanged();
- }
- }
-
- // Called in DisplayControllerHandler
private Mode recalculateMode(@Nullable HdrBrightnessData data) {
// no config
if (data == null) {
return Mode.NO_HDR;
}
+ // no HDR layer present
+ if (mHdrLayerSize == DEFAULT_HDR_LAYER_SIZE) {
+ return Mode.NO_HDR;
+ }
+ // low power mode and not allowed in low power mode
+ if (!data.allowInLowPowerMode && mLowPowerMode) {
+ return Mode.NO_HDR;
+ }
// HDR layer < minHdr % for Nbm
if (mHdrLayerSize < mScreenSize * data.minimumHdrPercentOfScreenForNbm) {
return Mode.NO_HDR;
@@ -270,6 +291,16 @@
return Mode.HBM_HDR;
}
+ private void onLowPowerModeChange() {
+ mLowPowerMode = mInjector.isLowPowerMode();
+ Mode newMode = recalculateMode(mHdrBrightnessData);
+ if (newMode != mMode) {
+ mMode = newMode;
+ mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET;
+ mClamperChangeListener.onChanged();
+ }
+ }
+
private float getMaxBrightness(Mode mode, float maxBrightness, HdrBrightnessData data) {
if (mode == Mode.NBM_HDR) {
return Math.min(data.hbmTransitionPoint, maxBrightness);
@@ -281,7 +312,13 @@
}
// Called in DisplayControllerHandler
- private float findBrightnessLimit(HdrBrightnessData data, float ambientLux) {
+ private float findBrightnessLimit(@Nullable HdrBrightnessData data, float ambientLux) {
+ if (data == null) {
+ return PowerManager.BRIGHTNESS_MAX;
+ }
+ if (ambientLux == INVALID_LUX) {
+ return PowerManager.BRIGHTNESS_MAX;
+ }
float foundAmbientBoundary = Float.MAX_VALUE;
float foundMaxBrightness = PowerManager.BRIGHTNESS_MAX;
for (Map.Entry<Float, Float> brightnessPoint :
@@ -299,7 +336,17 @@
// Called in DisplayControllerHandler
private void onHdrInfoChanged(float hdrLayerSize, float maxDesiredHdrSdrRatio) {
mHdrLayerSize = hdrLayerSize;
- recalculate(mHdrBrightnessData, maxDesiredHdrSdrRatio);
+ Mode newMode = recalculateMode(mHdrBrightnessData);
+ // mode changed, or mode was HDR and maxDesiredHdrRatio changed
+ boolean needToNotifyChange = mMode != newMode
+ || (mMode != HdrBrightnessModifier.Mode.NO_HDR
+ && !BrightnessSynchronizer.floatEquals(mMaxDesiredHdrRatio, maxDesiredHdrSdrRatio));
+ mMode = newMode;
+ mMaxDesiredHdrRatio = maxDesiredHdrSdrRatio;
+ if (needToNotifyChange) {
+ mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET;
+ mClamperChangeListener.onChanged();
+ }
}
// Called in DisplayControllerHandler
@@ -323,12 +370,36 @@
}
}
+ // Called in DisplayControllerHandler
+ private void registerContentObserver() {
+ if (!mContentObserverRegistered) {
+ mInjector.registerContentObserver(mContentObserver, mLowPowerModeSetting);
+ mContentObserverRegistered = true;
+ mLowPowerMode = mInjector.isLowPowerMode();
+ }
+ }
+
+ // Called in DisplayControllerHandler
+ private void unregisterContentObserver() {
+ if (mContentObserverRegistered) {
+ mInjector.unregisterContentObserver(mContentObserver);
+ mContentObserverRegistered = false;
+ mLowPowerMode = false;
+ }
+ }
+
private enum Mode {
NO_HDR, NBM_HDR, HBM_HDR
}
@SuppressLint("MissingPermission")
static class Injector {
+ private final Context mContext;
+
+ Injector(Context context) {
+ mContext = context;
+ }
+
void registerHdrListener(SurfaceControlHdrLayerInfoListener listener, IBinder token) {
listener.register(token);
}
@@ -336,5 +407,19 @@
void unregisterHdrListener(SurfaceControlHdrLayerInfoListener listener, IBinder token) {
listener.unregister(token);
}
+
+ void registerContentObserver(ContentObserver observer, Uri uri) {
+ mContext.getContentResolver().registerContentObserver(uri, false,
+ observer, UserHandle.USER_ALL);
+ }
+
+ void unregisterContentObserver(ContentObserver observer) {
+ mContext.getContentResolver().unregisterContentObserver(observer);
+ }
+
+ boolean isLowPowerMode() {
+ return Settings.Global.getInt(
+ mContext.getContentResolver(), Settings.Global.LOW_POWER_MODE, 0) != 0;
+ }
}
}
diff --git a/services/core/java/com/android/server/display/brightness/clamper/LightSensorController.java b/services/core/java/com/android/server/display/brightness/clamper/LightSensorController.java
index d89dd28..b219cb1 100644
--- a/services/core/java/com/android/server/display/brightness/clamper/LightSensorController.java
+++ b/services/core/java/com/android/server/display/brightness/clamper/LightSensorController.java
@@ -62,6 +62,9 @@
private final SensorEventListener mLightSensorEventListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
+ if (event.sensor != mRegisteredLightSensor) {
+ return;
+ }
long now = mInjector.getTime();
mAmbientFilter.addValue(TimeUnit.NANOSECONDS.toMillis(event.timestamp),
event.values[0]);
@@ -95,15 +98,13 @@
if (mRegisteredLightSensor == mLightSensor) {
return;
}
+ if (mLightSensor != null) {
+ mSensorManager.registerListener(mLightSensorEventListener,
+ mLightSensor, mLightSensorRate * 1000, mHandler);
+ }
if (mRegisteredLightSensor != null) {
stop();
}
- if (mLightSensor == null) {
- return;
- }
-
- mSensorManager.registerListener(mLightSensorEventListener,
- mLightSensor, mLightSensorRate * 1000, mHandler);
mRegisteredLightSensor = mLightSensor;
if (DEBUG) {
@@ -115,7 +116,7 @@
if (mRegisteredLightSensor == null) {
return;
}
- mSensorManager.unregisterListener(mLightSensorEventListener);
+ mSensorManager.unregisterListener(mLightSensorEventListener, mRegisteredLightSensor);
mRegisteredLightSensor = null;
mAmbientFilter.clear();
mLightSensorListener.onAmbientLuxChange(INVALID_LUX);
diff --git a/services/core/java/com/android/server/display/brightness/strategy/AutoBrightnessFallbackStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/AutoBrightnessFallbackStrategy.java
index d8b95ec..1db9bbe 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/AutoBrightnessFallbackStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/AutoBrightnessFallbackStrategy.java
@@ -16,6 +16,9 @@
package com.android.server.display.brightness.strategy;
+import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE;
+import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_OFF;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.Sensor;
@@ -23,7 +26,6 @@
import android.os.Handler;
import android.os.SystemClock;
import android.util.IndentingPrintWriter;
-import android.view.Display;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.BrightnessMappingStrategy;
@@ -53,7 +55,7 @@
Sensor mScreenOffBrightnessSensor;
// Indicates if the associated LogicalDisplay is enabled or not.
- private boolean mIsEnabled;
+ private boolean mIsDisplayEnabled;
// Represents if the associated display is a lead display or not. If not, the variable
// represents the lead display ID
@@ -97,7 +99,7 @@
public void dump(PrintWriter writer) {
writer.println("AutoBrightnessFallbackStrategy:");
writer.println(" mLeadDisplayId=" + mLeadDisplayId);
- writer.println(" mIsEnabled=" + mIsEnabled);
+ writer.println(" mIsDisplayEnabled=" + mIsDisplayEnabled);
if (mScreenOffBrightnessSensorController != null) {
IndentingPrintWriter ipw = new IndentingPrintWriter(writer, " ");
mScreenOffBrightnessSensorController.dump(ipw);
@@ -108,11 +110,10 @@
public void strategySelectionPostProcessor(
StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
if (mScreenOffBrightnessSensorController != null) {
- int targetDisplayState = strategySelectionNotifyRequest.getTargetDisplayState();
+ int policy = strategySelectionNotifyRequest.getDisplayPowerRequest().policy;
mScreenOffBrightnessSensorController.setLightSensorEnabled(
- strategySelectionNotifyRequest.isAutoBrightnessEnabled() && mIsEnabled
- && (targetDisplayState == Display.STATE_OFF
- || (targetDisplayState == Display.STATE_DOZE
+ strategySelectionNotifyRequest.isAutoBrightnessEnabled() && mIsDisplayEnabled
+ && (policy == POLICY_OFF || (policy == POLICY_DOZE
&& !strategySelectionNotifyRequest
.isAllowAutoBrightnessWhileDozingConfig()))
&& mLeadDisplayId == Layout.NO_LEAD_DISPLAY);
@@ -132,9 +133,9 @@
*/
public void setupAutoBrightnessFallbackSensor(SensorManager sensorManager,
DisplayDeviceConfig displayDeviceConfig, Handler handler,
- BrightnessMappingStrategy brightnessMappingStrategy, boolean isEnabled,
+ BrightnessMappingStrategy brightnessMappingStrategy, boolean isDisplayEnabled,
int leadDisplayId) {
- mIsEnabled = isEnabled;
+ mIsDisplayEnabled = isDisplayEnabled;
mLeadDisplayId = leadDisplayId;
if (mScreenOffBrightnessSensorController != null) {
mScreenOffBrightnessSensorController.stop();
diff --git a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
index d610f08..5e471c8 100644
--- a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
@@ -121,6 +121,7 @@
private static final int MSG_HIGH_BRIGHTNESS_THRESHOLDS_CHANGED = 6;
private static final int MSG_REFRESH_RATE_IN_HBM_SUNLIGHT_CHANGED = 7;
private static final int MSG_REFRESH_RATE_IN_HBM_HDR_CHANGED = 8;
+ private static final int MSG_SWITCH_USER = 9;
private final Object mLock = new Object();
private final Context mContext;
@@ -564,6 +565,13 @@
}
/**
+ * Called when the user switches.
+ */
+ public void onSwitchUser() {
+ mHandler.obtainMessage(MSG_SWITCH_USER).sendToTarget();
+ }
+
+ /**
* Print the object's state and debug information into the given stream.
*
* @param pw The stream to dump information to.
@@ -789,6 +797,13 @@
mHbmObserver.onDeviceConfigRefreshRateInHbmHdrChanged(refreshRateInHbmHdr);
break;
}
+
+ case MSG_SWITCH_USER: {
+ synchronized (mLock) {
+ mSettingsObserver.updateRefreshRateSettingLocked();
+ mSettingsObserver.updateModeSwitchingTypeSettingLocked();
+ }
+ }
}
}
}
@@ -1012,10 +1027,10 @@
final ContentResolver cr = mContext.getContentResolver();
mInjector.registerPeakRefreshRateObserver(cr, this);
mInjector.registerMinRefreshRateObserver(cr, this);
- cr.registerContentObserver(mLowPowerModeSetting, false /*notifyDescendants*/, this,
- UserHandle.USER_SYSTEM);
- cr.registerContentObserver(mMatchContentFrameRateSetting, false /*notifyDescendants*/,
- this);
+ cr.registerContentObserver(mLowPowerModeSetting, /* notifyDescendants= */ false, this,
+ UserHandle.USER_ALL);
+ cr.registerContentObserver(mMatchContentFrameRateSetting,
+ /* notifyDescendants= */ false, this, UserHandle.USER_ALL);
mInjector.registerDisplayListener(mDisplayListener, mHandler);
float deviceConfigDefaultPeakRefresh =
@@ -1156,14 +1171,15 @@
float highestRefreshRate = getMaxRefreshRateLocked(displayId);
float minRefreshRate = Settings.System.getFloatForUser(cr,
- Settings.System.MIN_REFRESH_RATE, 0f, cr.getUserId());
+ Settings.System.MIN_REFRESH_RATE, 0f, UserHandle.USER_CURRENT);
if (Float.isInfinite(minRefreshRate)) {
// Infinity means that we want the highest possible refresh rate
minRefreshRate = highestRefreshRate;
}
float peakRefreshRate = Settings.System.getFloatForUser(cr,
- Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate, cr.getUserId());
+ Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate,
+ UserHandle.USER_CURRENT);
if (Float.isInfinite(peakRefreshRate)) {
// Infinity means that we want the highest possible refresh rate
peakRefreshRate = highestRefreshRate;
@@ -1234,9 +1250,9 @@
private void updateModeSwitchingTypeSettingLocked() {
final ContentResolver cr = mContext.getContentResolver();
- int switchingType = Settings.Secure.getIntForUser(
- cr, Settings.Secure.MATCH_CONTENT_FRAME_RATE, mModeSwitchingType /*default*/,
- cr.getUserId());
+ int switchingType = Settings.Secure.getIntForUser(cr,
+ Settings.Secure.MATCH_CONTENT_FRAME_RATE, /* default= */ mModeSwitchingType,
+ UserHandle.USER_CURRENT);
if (switchingType != mModeSwitchingType) {
mModeSwitchingType = switchingType;
notifyDesiredDisplayModeSpecsChangedLocked();
@@ -3033,14 +3049,14 @@
public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr,
@NonNull ContentObserver observer) {
cr.registerContentObserver(PEAK_REFRESH_RATE_URI, false /*notifyDescendants*/,
- observer, UserHandle.USER_SYSTEM);
+ observer, UserHandle.USER_ALL);
}
@Override
public void registerMinRefreshRateObserver(@NonNull ContentResolver cr,
@NonNull ContentObserver observer) {
cr.registerContentObserver(MIN_REFRESH_RATE_URI, false /*notifyDescendants*/,
- observer, UserHandle.USER_SYSTEM);
+ observer, UserHandle.USER_ALL);
}
@Override
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index d43e783..a3b77e8 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -543,18 +543,20 @@
}
private void startDozingInternal(IBinder token, int screenState,
- @Display.StateReason int reason, int screenBrightness) {
+ @Display.StateReason int reason, float screenBrightnessFloat, int screenBrightnessInt) {
Slog.d(TAG, "Dream requested to start dozing: " + token
+ ", screenState=" + Display.stateToString(screenState)
+ ", reason=" + Display.stateReasonToString(reason)
- + ", screenBrightness=" + screenBrightness);
+ + ", screenBrightnessFloat=" + screenBrightnessFloat
+ + ", screenBrightnessInt=" + screenBrightnessInt);
synchronized (mLock) {
if (mCurrentDream != null && mCurrentDream.token == token && mCurrentDream.canDoze) {
mCurrentDream.dozeScreenState = screenState;
- mCurrentDream.dozeScreenBrightness = screenBrightness;
+ mCurrentDream.dozeScreenBrightness = screenBrightnessInt;
+ mCurrentDream.dozeScreenBrightnessFloat = screenBrightnessFloat;
mPowerManagerInternal.setDozeOverrideFromDreamManager(
- screenState, reason, screenBrightness);
+ screenState, reason, screenBrightnessFloat, screenBrightnessInt);
if (!mCurrentDream.isDozing) {
mCurrentDream.isDozing = true;
mDozeWakeLock.acquire();
@@ -575,6 +577,7 @@
mPowerManagerInternal.setDozeOverrideFromDreamManager(
Display.STATE_UNKNOWN,
Display.STATE_REASON_DREAM_MANAGER,
+ PowerManager.BRIGHTNESS_INVALID_FLOAT,
PowerManager.BRIGHTNESS_DEFAULT);
}
}
@@ -1095,7 +1098,7 @@
@Override // Binder call
public void startDozing(
IBinder token, int screenState, @Display.StateReason int reason,
- int screenBrightness) {
+ float screenBrightnessFloat, int screeBrightnessInt) {
// Requires no permission, called by Dream from an arbitrary process.
if (token == null) {
throw new IllegalArgumentException("token must not be null");
@@ -1103,7 +1106,8 @@
final long ident = Binder.clearCallingIdentity();
try {
- startDozingInternal(token, screenState, reason, screenBrightness);
+ startDozingInternal(token, screenState, reason, screenBrightnessFloat,
+ screeBrightnessInt);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -1112,7 +1116,7 @@
@Override // Binder call
public void startDozingOneway(
IBinder token, int screenState, @Display.StateReason int reason,
- int screenBrightness) {
+ float screenBrightnessFloat, int screeBrightnessInt) {
// Requires no permission, called by Dream from an arbitrary process.
if (token == null) {
throw new IllegalArgumentException("token must not be null");
@@ -1120,7 +1124,8 @@
final long ident = Binder.clearCallingIdentity();
try {
- startDozingInternal(token, screenState, reason, screenBrightness);
+ startDozingInternal(token, screenState, reason, screenBrightnessFloat,
+ screeBrightnessInt);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -1277,6 +1282,7 @@
public boolean isWaking = false;
public int dozeScreenState = Display.STATE_UNKNOWN;
public int dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
+ public float dozeScreenBrightnessFloat = PowerManager.BRIGHTNESS_INVALID_FLOAT;
DreamRecord(ComponentName name, int userId, boolean isPreview, boolean canDoze) {
this.name = name;
@@ -1297,6 +1303,7 @@
+ ", isWaking=" + isWaking
+ ", dozeScreenState=" + dozeScreenState
+ ", dozeScreenBrightness=" + dozeScreenBrightness
+ + ", dozeScreenBrightnessFloat=" + dozeScreenBrightnessFloat
+ '}';
}
}
diff --git a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
index e242164..e0aa9bf 100644
--- a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
+++ b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
@@ -21,11 +21,13 @@
import static com.android.server.grammaticalinflection.GrammaticalInflectionUtils.checkSystemGrammaticalGenderPermission;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.GrammaticalInflectionManager;
import android.app.IGrammaticalInflectionManager;
import android.content.AttributionSource;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.res.Configuration;
import android.os.Binder;
@@ -36,6 +38,7 @@
import android.os.ShellCallback;
import android.os.SystemProperties;
import android.os.Trace;
+import android.os.UserManager;
import android.permission.PermissionManager;
import android.util.AtomicFile;
import android.util.Log;
@@ -271,6 +274,31 @@
throw new IllegalArgumentException("Unknown grammatical gender");
}
+ // TODO(b/356895553): Don't allow profiles and background user to change system
+ // grammaticalinflection
+ if (UserManager.isVisibleBackgroundUsersEnabled()
+ && mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE)) {
+ // The check is added only for automotive devices. On automotive devices, it is
+ // possible that multiple users are visible simultaneously using visible background
+ // users. In such cases, it is desired that only the current user (not the visible
+ // background user) can change the GrammaticalInflection of the device.
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ int currentUser = ActivityManager.getCurrentUser();
+ if (userId != currentUser) {
+ Log.w(TAG,
+ "Only current user is allowed to update GrammaticalInflection if "
+ + "visible background users are enabled. Current User"
+ + currentUser + ". Calling User: " + userId);
+ throw new SecurityException("Only current user is allowed to update "
+ + "GrammaticalInflection.");
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
final File file = getGrammaticalGenderFile(userId);
synchronized (mLock) {
final AtomicFile atomicFile = new AtomicFile(file);
diff --git a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
index 42a99de..b0dff22 100644
--- a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
+++ b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
@@ -28,7 +28,6 @@
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED;
import static android.view.WindowManager.LayoutParams.SoftInputModeFlags;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static com.android.internal.inputmethod.InputMethodDebug.softInputModeToString;
import static com.android.internal.inputmethod.SoftInputShowHideReason.REMOVE_IME_SCREENSHOT_FROM_IMMS;
@@ -59,7 +58,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.inputmethod.SoftInputShowHideReason;
import com.android.server.LocalServices;
-import com.android.server.wm.ImeTargetChangeListener;
import com.android.server.wm.WindowManagerInternal;
import java.io.PrintWriter;
@@ -76,6 +74,9 @@
private static final boolean DEBUG = InputMethodManagerService.DEBUG;
+ @UserIdInt
+ private final int mUserId;
+
private final InputMethodManagerService mService;
private final WindowManagerInternal mWindowManagerInternal;
@@ -184,73 +185,64 @@
*/
private final ImeVisibilityPolicy mPolicy;
- public ImeVisibilityStateComputer(@NonNull InputMethodManagerService service) {
+ public ImeVisibilityStateComputer(@NonNull InputMethodManagerService service,
+ @UserIdInt int userId) {
this(service,
LocalServices.getService(WindowManagerInternal.class),
LocalServices.getService(WindowManagerInternal.class)::getDisplayImePolicy,
- new ImeVisibilityPolicy());
+ new ImeVisibilityPolicy(), userId);
}
@VisibleForTesting
public ImeVisibilityStateComputer(@NonNull InputMethodManagerService service,
@NonNull Injector injector) {
this(service, injector.getWmService(), injector.getImeValidator(),
- new ImeVisibilityPolicy());
+ new ImeVisibilityPolicy(), injector.getUserId());
}
interface Injector {
- default WindowManagerInternal getWmService() {
- return null;
- }
+ @NonNull
+ WindowManagerInternal getWmService();
- default InputMethodManagerService.ImeDisplayValidator getImeValidator() {
- return null;
- }
+ @NonNull
+ InputMethodManagerService.ImeDisplayValidator getImeValidator();
+
+ @UserIdInt
+ int getUserId();
}
private ImeVisibilityStateComputer(InputMethodManagerService service,
WindowManagerInternal wmService,
InputMethodManagerService.ImeDisplayValidator imeDisplayValidator,
- ImeVisibilityPolicy imePolicy) {
+ ImeVisibilityPolicy imePolicy, @UserIdInt int userId) {
+ mUserId = userId;
mService = service;
mWindowManagerInternal = wmService;
mImeDisplayValidator = imeDisplayValidator;
mPolicy = imePolicy;
- mWindowManagerInternal.setInputMethodTargetChangeListener(new ImeTargetChangeListener() {
- @Override
- public void onImeTargetOverlayVisibilityChanged(@NonNull IBinder overlayWindowToken,
- @WindowManager.LayoutParams.WindowType int windowType, boolean visible,
- boolean removed) {
- // Ignoring the starting window since it's ok to cover the IME target
- // window in temporary without affecting the IME visibility.
- final boolean hasOverlay = visible && !removed
- && windowType != TYPE_APPLICATION_STARTING;
- synchronized (ImfLock.class) {
- mHasVisibleImeLayeringOverlay = hasOverlay;
- }
- }
+ }
- @Override
- public void onImeInputTargetVisibilityChanged(IBinder imeInputTarget,
- boolean visibleRequested, boolean removed) {
- final boolean visibleAndNotRemoved = visibleRequested && !removed;
- synchronized (ImfLock.class) {
- if (visibleAndNotRemoved) {
- mCurVisibleImeInputTarget = imeInputTarget;
- return;
- }
- if (mHasVisibleImeLayeringOverlay
- && mCurVisibleImeInputTarget == imeInputTarget) {
- final int reason = SoftInputShowHideReason.HIDE_WHEN_INPUT_TARGET_INVISIBLE;
- final var statsToken = ImeTracker.forLogging().onStart(ImeTracker.TYPE_HIDE,
- ImeTracker.ORIGIN_SERVER, reason, false /* fromUser */);
- mService.onApplyImeVisibilityFromComputerLocked(imeInputTarget, statsToken,
- new ImeVisibilityResult(STATE_HIDE_IME_EXPLICIT, reason));
- }
- mCurVisibleImeInputTarget = null;
- }
- }
- });
+ @GuardedBy("ImfLock.class")
+ void setHasVisibleImeLayeringOverlay(boolean hasVisibleOverlay) {
+ mHasVisibleImeLayeringOverlay = hasVisibleOverlay;
+ }
+
+ @GuardedBy("ImfLock.class")
+ void onImeInputTargetVisibilityChanged(@NonNull IBinder imeInputTarget,
+ boolean visibleAndNotRemoved) {
+ if (visibleAndNotRemoved) {
+ mCurVisibleImeInputTarget = imeInputTarget;
+ return;
+ }
+ if (mHasVisibleImeLayeringOverlay
+ && mCurVisibleImeInputTarget == imeInputTarget) {
+ final int reason = SoftInputShowHideReason.HIDE_WHEN_INPUT_TARGET_INVISIBLE;
+ final var statsToken = ImeTracker.forLogging().onStart(ImeTracker.TYPE_HIDE,
+ ImeTracker.ORIGIN_SERVER, reason, false /* fromUser */);
+ mService.onApplyImeVisibilityFromComputerLocked(imeInputTarget, statsToken,
+ new ImeVisibilityResult(STATE_HIDE_IME_EXPLICIT, reason), mUserId);
+ }
+ mCurVisibleImeInputTarget = null;
}
/**
@@ -631,6 +623,12 @@
return mWindowManagerInternal.shouldRestoreImeVisibility(getWindowTokenFrom(state));
}
+ @UserIdInt
+ @VisibleForTesting
+ int getUserId() {
+ return mUserId;
+ }
+
@GuardedBy("ImfLock.class")
boolean isInputShown() {
return mInputShown;
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
index 03cbab5..94b1473 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
@@ -463,7 +463,8 @@
// should now try to restart the service for us.
mLastBindTime = SystemClock.uptimeMillis();
clearCurMethodAndSessions();
- mService.mVisibilityStateComputer.setInputShown(false);
+ final var userData = mService.getUserData(mUserId);
+ userData.mVisibilityStateComputer.setInputShown(false);
mService.unbindCurrentClientLocked(UnbindReason.DISCONNECT_IME, mUserId);
}
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 5e7d391..1c0a082 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -44,6 +44,7 @@
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.DISPLAY_IME_POLICY_HIDE;
import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.inputmethod.ConnectionlessHandwritingCallback.CONNECTIONLESS_HANDWRITING_ERROR_OTHER;
import static android.view.inputmethod.ConnectionlessHandwritingCallback.CONNECTIONLESS_HANDWRITING_ERROR_UNSUPPORTED;
@@ -187,6 +188,7 @@
import com.android.server.pm.UserManagerInternal;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.utils.PriorityDump;
+import com.android.server.wm.ImeTargetChangeListener;
import com.android.server.wm.WindowManagerInternal;
import java.io.FileDescriptor;
@@ -419,11 +421,6 @@
private final InputMethodMenuControllerNew mMenuControllerNew;
@GuardedBy("ImfLock.class")
- @MultiUserUnawareField
- @NonNull
- final ImeVisibilityStateComputer mVisibilityStateComputer;
-
- @GuardedBy("ImfLock.class")
@SharedByAllUsersField
@NonNull
private final DefaultImeVisibilityApplier mVisibilityApplier;
@@ -619,7 +616,7 @@
case Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD: {
if (!mNewInputMethodSwitcherMenuEnabled) {
if (userId == mCurrentUserId) {
- mMenuController.updateKeyboardFromSettingsLocked();
+ mMenuController.updateKeyboardFromSettingsLocked(userId);
}
}
break;
@@ -628,10 +625,11 @@
final int accessibilitySoftKeyboardSetting = Settings.Secure.getIntForUser(
mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0, userId);
- mVisibilityStateComputer.getImePolicy().setA11yRequestNoSoftKeyboard(
- accessibilitySoftKeyboardSetting);
final var userData = getUserData(userId);
- if (mVisibilityStateComputer.getImePolicy().isA11yRequestNoSoftKeyboard()) {
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
+ visibilityStateComputer.getImePolicy().setA11yRequestNoSoftKeyboard(
+ accessibilitySoftKeyboardSetting);
+ if (visibilityStateComputer.getImePolicy().isA11yRequestNoSoftKeyboard()) {
hideCurrentInputLocked(userData.mImeBindingState.mFocusedWindow,
0 /* flags */, SoftInputShowHideReason.HIDE_SETTINGS_ON_CHANGE, userId);
} else if (isShowRequestedForCurrentWindow(userId)) {
@@ -678,22 +676,18 @@
}
// sender userId can be a real user ID or USER_ALL.
final int senderUserId = pendingResult.getSendingUserId();
- if (senderUserId != UserHandle.USER_ALL) {
- synchronized (ImfLock.class) {
- if (senderUserId != mCurrentUserId) {
- // A background user is trying to hide the dialog. Ignore.
- return;
- }
+ synchronized (ImfLock.class) {
+ if (senderUserId != UserHandle.USER_ALL && senderUserId != mCurrentUserId) {
+ // A background user is trying to hide the dialog. Ignore.
+ return;
}
- }
- if (mNewInputMethodSwitcherMenuEnabled) {
- synchronized (ImfLock.class) {
- final var bindingController = getInputMethodBindingController(senderUserId);
- mMenuControllerNew.hide(bindingController.getCurTokenDisplayId(),
- senderUserId);
+ final int userId = mCurrentUserId;
+ if (mNewInputMethodSwitcherMenuEnabled) {
+ final var bindingController = getInputMethodBindingController(userId);
+ mMenuControllerNew.hide(bindingController.getCurTokenDisplayId(), userId);
+ } else {
+ mMenuController.hideInputMethodMenuLocked(userId);
}
- } else {
- mMenuController.hideInputMethodMenu();
}
} else {
Slog.w(TAG, "Unexpected intent " + intent);
@@ -707,6 +701,7 @@
* <p>Note: For historical reasons, {@link Intent#ACTION_LOCALE_CHANGED} has been sent to all
* the users.</p>
*/
+ @WorkerThread
void onActionLocaleChanged(@NonNull LocaleList prevLocales, @NonNull LocaleList newLocales) {
if (DEBUG) {
Slog.d(TAG, "onActionLocaleChanged prev=" + prevLocales + " new=" + newLocales);
@@ -716,13 +711,19 @@
return;
}
for (int userId : mUserManagerInternal.getUserIds()) {
- final InputMethodSettings settings = queryInputMethodServicesInternal(
- mContext,
- userId,
- AdditionalSubtypeMapRepository.get(userId),
- DirectBootAwareness.AUTO);
- InputMethodSettingsRepository.put(userId, settings);
-
+ // Does InputMethodInfo really have data dependency on system locale?
+ // TODO(b/356679261): Check if we really need to update RawInputMethodInfo here.
+ {
+ final var userData = getUserData(userId);
+ final var additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId);
+ final var rawMethodMap = queryRawInputMethodServiceMap(mContext, userId);
+ userData.mRawInputMethodMap.set(rawMethodMap);
+ final var methodMap = rawMethodMap.toInputMethodMap(additionalSubtypeMap,
+ DirectBootAwareness.AUTO,
+ mUserManagerInternal.isUserUnlockingOrUnlocked(userId));
+ final var settings = InputMethodSettings.create(methodMap, userId);
+ InputMethodSettingsRepository.put(userId, settings);
+ }
postInputMethodSettingUpdatedLocked(true /* resetDefaultEnabledIme */, userId);
// If the locale is changed, needs to reset the default ime
resetDefaultImeLocked(mContext, userId);
@@ -796,17 +797,13 @@
private void onFinishPackageChangesInternal() {
final int userId = getChangingUserId();
+ final var userData = getUserData(userId);
// Instantiating InputMethodInfo requires disk I/O.
// Do them before acquiring the lock to minimize the chances of ANR (b/340221861).
- final var newMethodMapWithoutAdditionalSubtypes =
- queryInputMethodServicesInternal(mContext, userId,
- AdditionalSubtypeMap.EMPTY_MAP, DirectBootAwareness.AUTO)
- .getMethodMap();
+ userData.mRawInputMethodMap.set(queryRawInputMethodServiceMap(mContext, userId));
synchronized (ImfLock.class) {
- final AdditionalSubtypeMap additionalSubtypeMap =
- AdditionalSubtypeMapRepository.get(userId);
final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
InputMethodInfo curIm = null;
@@ -836,6 +833,7 @@
}
// Clear additional subtypes as a batch operation.
+ final var additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId);
final AdditionalSubtypeMap newAdditionalSubtypeMap =
additionalSubtypeMap.cloneWithRemoveOrSelf(imesToClearAdditionalSubtypes);
final boolean additionalSubtypeChanged =
@@ -845,8 +843,10 @@
settings.getMethodMap());
}
- final var newMethodMap = newMethodMapWithoutAdditionalSubtypes
- .applyAdditionalSubtypes(newAdditionalSubtypeMap);
+ final var newMethodMap = userData.mRawInputMethodMap.get().toInputMethodMap(
+ newAdditionalSubtypeMap,
+ DirectBootAwareness.AUTO,
+ mUserManagerInternal.isUserUnlockingOrUnlocked(userId));
if (InputMethodMap.areSame(settings.getMethodMap(), newMethodMap)) {
// No update in the actual IME map.
@@ -964,6 +964,37 @@
InputMethodDrawsNavBarResourceMonitor.registerCallback(context, mService.mIoHandler,
mService::onUpdateResourceOverlay);
+ // Also hook up ImeTargetChangeListener.
+ // TODO(b/356876005): Merge this into InputMethodManagerInternal.
+ final var windowManagerInternal = mService.mWindowManagerInternal;
+ windowManagerInternal.setInputMethodTargetChangeListener(new ImeTargetChangeListener() {
+ @Override
+ public void onImeTargetOverlayVisibilityChanged(@NonNull IBinder overlayWindowToken,
+ @WindowManager.LayoutParams.WindowType int windowType, boolean visible,
+ boolean removed, int displayId) {
+ // Ignoring the starting window since it's ok to cover the IME target
+ // window in temporary without affecting the IME visibility.
+ final boolean hasOverlay = visible && !removed
+ && windowType != TYPE_APPLICATION_STARTING;
+ synchronized (ImfLock.class) {
+ final var userId = mService.resolveImeUserIdFromDisplayIdLocked(displayId);
+ mService.getUserData(userId).mVisibilityStateComputer
+ .setHasVisibleImeLayeringOverlay(hasOverlay);
+ }
+ }
+
+ @Override
+ public void onImeInputTargetVisibilityChanged(IBinder imeInputTarget,
+ boolean visibleRequested, boolean removed, int displayId) {
+ final boolean visibleAndNotRemoved = visibleRequested && !removed;
+ synchronized (ImfLock.class) {
+ final var userId = mService.resolveImeUserIdFromDisplayIdLocked(displayId);
+ mService.getUserData(userId).mVisibilityStateComputer
+ .onImeInputTargetVisibilityChanged(imeInputTarget,
+ visibleAndNotRemoved);
+ }
+ }
+ });
// Also schedule user init tasks onto an I/O thread.
initializeUsersAsync(mService.mUserManagerInternal.getUserIds());
}
@@ -987,8 +1018,6 @@
@NonNull
private static InputMethodManagerService createServiceForProduction(
@NonNull Context context) {
- // TODO(b/196206770): Disallow I/O on this thread. Currently it's needed for loading
- // additional subtypes in switchUserOnHandlerLocked().
final ServiceThread thread = new ServiceThread(HANDLER_THREAD_NAME,
Process.THREAD_PRIORITY_FOREGROUND, false /* allowIo */);
thread.start();
@@ -997,6 +1026,8 @@
Process.THREAD_PRIORITY_FOREGROUND, true /* allowIo */);
ioThread.start();
+ SecureSettingsWrapper.setContentResolver(context.getContentResolver());
+
return new InputMethodManagerService(context,
shouldEnableConcurrentMultiUserMode(context), thread.getLooper(),
Handler.createAsync(ioThread.getLooper()),
@@ -1055,6 +1086,7 @@
public void onUserRemoved(UserInfo user) {
// Called directly from UserManagerService. Do not block the calling thread.
final int userId = user.id;
+ SecureSettingsWrapper.onUserRemoved(userId);
AdditionalSubtypeMapRepository.remove(userId);
InputMethodSettingsRepository.remove(userId);
mService.mUserDataRepository.remove(userId);
@@ -1066,9 +1098,11 @@
final int userId = user.getUserIdentifier();
SecureSettingsWrapper.onUserUnlocking(userId);
mService.mIoHandler.post(() -> {
- final var settings = queryInputMethodServicesInternal(mService.mContext, userId,
- AdditionalSubtypeMapRepository.get(userId), DirectBootAwareness.AUTO);
- InputMethodSettingsRepository.put(userId, settings);
+ final var userData = mService.getUserData(userId);
+ final var methodMap = userData.mRawInputMethodMap.get().toInputMethodMap(
+ AdditionalSubtypeMapRepository.get(userId), DirectBootAwareness.AUTO, true);
+ final var newSettings = InputMethodSettings.create(methodMap, userId);
+ InputMethodSettingsRepository.put(userId, newSettings);
synchronized (ImfLock.class) {
if (!mService.mSystemReady) {
return;
@@ -1106,19 +1140,22 @@
for (int userId : userIds) {
Slog.d(TAG, "Start initialization for user=" + userId);
+ final var userData = mService.getUserData(userId);
+
AdditionalSubtypeMapRepository.initializeIfNecessary(userId);
final var additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId);
- final var settings = InputMethodManagerService.queryInputMethodServicesInternal(
- context, userId, additionalSubtypeMap,
- DirectBootAwareness.AUTO).getMethodMap();
- InputMethodSettingsRepository.put(userId,
- InputMethodSettings.create(settings, userId));
+ final var rawMethodMap = queryRawInputMethodServiceMap(context, userId);
+ userData.mRawInputMethodMap.set(rawMethodMap);
+ final var methodMap = rawMethodMap.toInputMethodMap(additionalSubtypeMap,
+ DirectBootAwareness.AUTO,
+ userManagerInternal.isUserUnlockingOrUnlocked(userId));
+ final var settings = InputMethodSettings.create(methodMap, userId);
+ InputMethodSettingsRepository.put(userId, settings);
final int profileParentId = userManagerInternal.getProfileParentId(userId);
final boolean value =
InputMethodDrawsNavBarResourceMonitor.evaluate(context,
profileParentId);
- final var userData = mService.getUserData(userId);
userData.mImeDrawsNavBar.set(value);
userData.mBackgroundLoadLatch.countDown();
@@ -1133,12 +1170,13 @@
// Called on ActivityManager thread.
SecureSettingsWrapper.onUserStopped(userId);
mService.mIoHandler.post(() -> {
+ final var userData = mService.getUserData(userId);
final var additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId);
- final var settings = InputMethodManagerService.queryInputMethodServicesInternal(
- mService.mContext, userId, additionalSubtypeMap,
- DirectBootAwareness.AUTO).getMethodMap();
+ final var rawMethodMap = userData.mRawInputMethodMap.get();
+ final var methodMap = rawMethodMap.toInputMethodMap(additionalSubtypeMap,
+ DirectBootAwareness.AUTO, false /* userUnlocked */);
InputMethodSettingsRepository.put(userId,
- InputMethodSettings.create(settings, userId));
+ InputMethodSettings.create(methodMap, userId));
});
}
}
@@ -1175,11 +1213,10 @@
mConcurrentMultiUserModeEnabled = concurrentMultiUserModeEnabled;
mContext = context;
mRes = context.getResources();
- SecureSettingsWrapper.onStart(mContext);
mHandler = Handler.createAsync(uiLooper, this);
mIoHandler = ioHandler;
- SystemLocaleWrapper.onStart(context, this::onActionLocaleChanged, mHandler);
+ SystemLocaleWrapper.onStart(context, this::onActionLocaleChanged, mIoHandler);
mImeTrackerService = new ImeTrackerService(mHandler);
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
@@ -1195,17 +1232,19 @@
mShowOngoingImeSwitcherForPhones = false;
mCurrentUserId = mActivityManagerInternal.getCurrentUserId();
- @SuppressWarnings("GuardedBy") final IntFunction<InputMethodBindingController>
+ final IntFunction<InputMethodBindingController>
bindingControllerFactory = userId -> new InputMethodBindingController(userId,
InputMethodManagerService.this);
+ final IntFunction<ImeVisibilityStateComputer> visibilityStateComputerFactory =
+ userId -> new ImeVisibilityStateComputer(InputMethodManagerService.this,
+ userId);
mUserDataRepository = new UserDataRepository(
bindingControllerForTesting != null ? bindingControllerForTesting
- : bindingControllerFactory);
+ : bindingControllerFactory, visibilityStateComputerFactory);
mMenuController = new InputMethodMenuController(this);
mMenuControllerNew = mNewInputMethodSwitcherMenuEnabled
? new InputMethodMenuControllerNew() : null;
- mVisibilityStateComputer = new ImeVisibilityStateComputer(this);
mVisibilityApplier = new DefaultImeVisibilityApplier(this);
mClientController = new ClientController(mPackageManagerInternal);
@@ -1223,12 +1262,6 @@
}
}
- @GuardedBy("ImfLock.class")
- @UserIdInt
- int getCurrentImeUserIdLocked() {
- return mCurrentUserId;
- }
-
private final class InkWindowInitializer implements Runnable {
public void run() {
synchronized (ImfLock.class) {
@@ -1240,12 +1273,12 @@
}
}
- private void onUpdateEditorToolType(int toolType) {
- synchronized (ImfLock.class) {
- IInputMethodInvoker curMethod = getCurMethodLocked();
- if (curMethod != null) {
- curMethod.updateEditorToolType(toolType);
- }
+ @GuardedBy("ImfLock.class")
+ private void onUpdateEditorToolTypeLocked(@MotionEvent.ToolType int toolType,
+ @UserIdInt int userId) {
+ final var curMethod = getInputMethodBindingController(userId).getCurMethod();
+ if (curMethod != null) {
+ curMethod.updateEditorToolType(toolType);
}
}
@@ -1410,7 +1443,7 @@
final int currentUserId = mCurrentUserId;
mStatusBarManagerInternal =
LocalServices.getService(StatusBarManagerInternal.class);
- hideStatusBarIconLocked();
+ hideStatusBarIconLocked(currentUserId);
final var bindingController = getInputMethodBindingController(currentUserId);
updateSystemUiLocked(bindingController.getImeWindowVis(),
bindingController.getBackDisposition(), currentUserId);
@@ -1642,15 +1675,11 @@
private List<InputMethodInfo> getInputMethodListInternal(@UserIdInt int userId,
@DirectBootAwareness int directBootAwareness, int callingUid) {
- final InputMethodSettings settings;
- if (directBootAwareness == DirectBootAwareness.AUTO) {
- settings = InputMethodSettingsRepository.get(userId);
- } else {
- final AdditionalSubtypeMap additionalSubtypeMap =
- AdditionalSubtypeMapRepository.get(userId);
- settings = queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap,
- directBootAwareness);
- }
+ final var userData = getUserData(userId);
+ final var methodMap = userData.mRawInputMethodMap.get().toInputMethodMap(
+ AdditionalSubtypeMapRepository.get(userId), directBootAwareness,
+ mUserManagerInternal.isUserUnlockingOrUnlocked(userId));
+ final var settings = InputMethodSettings.create(methodMap, userId);
// Create a copy.
final ArrayList<InputMethodInfo> methodList = new ArrayList<>(settings.getMethodList());
// filter caller's access to input methods
@@ -1827,7 +1856,7 @@
if (mNewInputMethodSwitcherMenuEnabled) {
mMenuControllerNew.hide(bindingController.getCurTokenDisplayId(), userId);
} else {
- mMenuController.hideInputMethodMenuLocked();
+ mMenuController.hideInputMethodMenuLocked(userId);
}
}
}
@@ -1840,10 +1869,11 @@
@GuardedBy("ImfLock.class")
void onUnbindCurrentMethodByReset(@UserIdInt int userId) {
final var userData = getUserData(userId);
- final ImeTargetWindowState winState = mVisibilityStateComputer.getWindowStateOrNull(
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
+ final ImeTargetWindowState winState = visibilityStateComputer.getWindowStateOrNull(
userData.mImeBindingState.mFocusedWindow);
if (winState != null && !winState.isRequestedImeVisible()
- && !mVisibilityStateComputer.isInputShown()) {
+ && !visibilityStateComputer.isInputShown()) {
// Normally, the focus window will apply the IME visibility state to
// WindowManager when the IME has applied it. But it would be too late when
// switching IMEs in between different users. (Since the focused IME will
@@ -1862,8 +1892,8 @@
@GuardedBy("ImfLock.class")
private boolean isShowRequestedForCurrentWindow(@UserIdInt int userId) {
final var userData = getUserData(userId);
- // TODO(b/349904272): Make mVisibilityStateComputer multi-user aware
- final ImeTargetWindowState state = mVisibilityStateComputer.getWindowStateOrNull(
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
+ final ImeTargetWindowState state = visibilityStateComputer.getWindowStateOrNull(
userData.mImeBindingState.mFocusedWindow);
return state != null && state.isRequestedImeVisible();
}
@@ -1927,8 +1957,9 @@
: createStatsTokenForFocusedClient(true /* show */,
SoftInputShowHideReason.ATTACH_NEW_INPUT, userId);
userData.mCurStatsToken = null;
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
showCurrentInputLocked(userData.mImeBindingState.mFocusedWindow, statsToken,
- mVisibilityStateComputer.getShowFlags(), MotionEvent.TOOL_TYPE_UNKNOWN,
+ visibilityStateComputer.getShowFlags(), MotionEvent.TOOL_TYPE_UNKNOWN,
null /* resultReceiver */, SoftInputShowHideReason.ATTACH_NEW_INPUT,
userId);
}
@@ -2009,17 +2040,18 @@
final int userId = bindingController.getUserId();
final var userData = getUserData(userId);
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
// Compute the final shown display ID with validated cs.selfReportedDisplayId for this
// session & other conditions.
- ImeTargetWindowState winState = mVisibilityStateComputer.getWindowStateOrNull(
+ ImeTargetWindowState winState = visibilityStateComputer.getWindowStateOrNull(
userData.mImeBindingState.mFocusedWindow);
if (winState == null) {
return InputBindResult.NOT_IME_TARGET_WINDOW;
}
final int csDisplayId = cs.mSelfReportedDisplayId;
bindingController.setDisplayIdToShowIme(
- mVisibilityStateComputer.computeImeDisplayId(winState, csDisplayId));
+ visibilityStateComputer.computeImeDisplayId(winState, csDisplayId));
// Potentially override the selected input method if the new display belongs to a virtual
// device with a custom IME.
@@ -2027,14 +2059,14 @@
final String deviceMethodId = computeCurrentDeviceMethodIdLocked(
bindingController.getUserId(), selectedMethodId);
if (deviceMethodId == null) {
- mVisibilityStateComputer.getImePolicy().setImeHiddenByDisplayPolicy(true);
+ visibilityStateComputer.getImePolicy().setImeHiddenByDisplayPolicy(true);
} else if (!Objects.equals(deviceMethodId, selectedMethodId)) {
setInputMethodLocked(deviceMethodId, NOT_A_SUBTYPE_ID,
bindingController.getDeviceIdToShowIme(), userId);
selectedMethodId = deviceMethodId;
}
- if (mVisibilityStateComputer.getImePolicy().isImeHiddenByDisplayPolicy()) {
+ if (visibilityStateComputer.getImePolicy().isImeHiddenByDisplayPolicy()) {
hideCurrentInputLocked(userData.mImeBindingState.mFocusedWindow, 0 /* flags */,
SoftInputShowHideReason.HIDE_DISPLAY_IME_POLICY_HIDE, userId);
return InputBindResult.NO_IME;
@@ -2554,7 +2586,7 @@
userData.mEnabledAccessibilitySessions.clear();
scheduleNotifyImeUidToAudioService(Process.INVALID_UID);
}
- hideStatusBarIconLocked();
+ hideStatusBarIconLocked(userId);
getUserData(userId).mInFullscreenMode = false;
mWindowManagerInternal.setDismissImeOnBackKeyPressed(false);
scheduleResetStylusHandwriting();
@@ -2565,6 +2597,11 @@
@DrawableRes int iconId, @NonNull UserData userData) {
final int userId = userData.mUserId;
synchronized (ImfLock.class) {
+ // To minimize app compat risk, ignore background users' request for single-user mode.
+ // TODO(b/357178609): generalize the logic and remove this special rule.
+ if (!mConcurrentMultiUserModeEnabled && userId != mCurrentUserId) {
+ return;
+ }
if (!calledWithValidTokenLocked(token, userData)) {
return;
}
@@ -2572,7 +2609,7 @@
try {
if (iconId == 0) {
if (DEBUG) Slog.d(TAG, "hide the small icon for the input method");
- hideStatusBarIconLocked();
+ hideStatusBarIconLocked(userId);
} else if (packageName != null) {
if (DEBUG) Slog.d(TAG, "show a small icon for the input method");
final PackageManager userAwarePackageManager =
@@ -2600,7 +2637,12 @@
}
@GuardedBy("ImfLock.class")
- private void hideStatusBarIconLocked() {
+ private void hideStatusBarIconLocked(@UserIdInt int userId) {
+ // To minimize app compat risk, ignore background users' request for single-user mode.
+ // TODO(b/357178609): generalize the logic and remove this special rule.
+ if (!mConcurrentMultiUserModeEnabled && userId != mCurrentUserId) {
+ return;
+ }
if (mStatusBarManagerInternal != null) {
mStatusBarManagerInternal.setIconVisibility(mSlotIme, false);
}
@@ -2779,9 +2821,10 @@
}
final IBinder targetWindow = mImeTargetWindowMap.get(startInputToken);
if (targetWindow != null) {
- mWindowManagerInternal.updateInputMethodTargetWindow(token, targetWindow);
+ mWindowManagerInternal.updateInputMethodTargetWindow(targetWindow);
}
- mVisibilityStateComputer.setLastImeTargetWindow(targetWindow);
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
+ visibilityStateComputer.setLastImeTargetWindow(targetWindow);
}
}
@@ -2806,6 +2849,11 @@
@GuardedBy("ImfLock.class")
private void updateSystemUiLocked(int vis, int backDisposition, @UserIdInt int userId) {
+ // To minimize app compat risk, ignore background users' request for single-user mode.
+ // TODO(b/357178609): generalize the logic and remove this special rule.
+ if (!mConcurrentMultiUserModeEnabled && userId != mCurrentUserId) {
+ return;
+ }
final var userData = getUserData(userId);
final var bindingController = userData.mBindingController;
final var curToken = bindingController.getCurToken();
@@ -2849,8 +2897,8 @@
}
final boolean needsToShowImeSwitcher = shouldShowImeSwitcherLocked(vis, userId);
if (mStatusBarManagerInternal != null) {
- mStatusBarManagerInternal.setImeWindowStatus(curTokenDisplayId,
- curToken, vis, backDisposition, needsToShowImeSwitcher);
+ mStatusBarManagerInternal.setImeWindowStatus(curTokenDisplayId, vis,
+ backDisposition, needsToShowImeSwitcher);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -2861,7 +2909,7 @@
void updateFromSettingsLocked(boolean enabledMayChange, @UserIdInt int userId) {
updateInputMethodsFromSettingsLocked(enabledMayChange, userId);
if (!mNewInputMethodSwitcherMenuEnabled) {
- mMenuController.updateKeyboardFromSettingsLocked();
+ mMenuController.updateKeyboardFromSettingsLocked(userId);
}
}
@@ -3044,8 +3092,14 @@
}
@GuardedBy("ImfLock.class")
- private void sendResultReceiverFailureLocked(@Nullable ResultReceiver resultReceiver) {
- final boolean isInputShown = mVisibilityStateComputer.isInputShown();
+ private void sendResultReceiverFailureLocked(@Nullable ResultReceiver resultReceiver,
+ @UserIdInt int userId) {
+ if (resultReceiver == null) {
+ return;
+ }
+ final var userData = getUserData(userId);
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
+ final boolean isInputShown = visibilityStateComputer.isInputShown();
resultReceiver.send(isInputShown
? InputMethodManager.RESULT_UNCHANGED_SHOWN
: InputMethodManager.RESULT_UNCHANGED_HIDDEN, null);
@@ -3060,12 +3114,15 @@
ImeTracing.getInstance().triggerManagerServiceDump(
"InputMethodManagerService#showSoftInput", mDumper);
synchronized (ImfLock.class) {
+ final int uid = Binder.getCallingUid();
+ final int callingUserId = UserHandle.getUserId(uid);
+ final int userId = resolveImeUserIdLocked(callingUserId);
final boolean result = showSoftInputLocked(client, windowToken, statsToken, flags,
- lastClickToolType, resultReceiver, reason);
+ lastClickToolType, resultReceiver, reason, uid, userId);
// When ZeroJankProxy is enabled, the app has already received "true" as the return
// value, and expect "resultReceiver" to be notified later. See b/327751155.
if (!result && Flags.useZeroJankProxy()) {
- sendResultReceiverFailureLocked(resultReceiver);
+ sendResultReceiverFailureLocked(resultReceiver, userId);
}
return result; // ignored when ZeroJankProxy is enabled.
}
@@ -3075,10 +3132,7 @@
private boolean showSoftInputLocked(IInputMethodClient client, IBinder windowToken,
@NonNull ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
int lastClickToolType, ResultReceiver resultReceiver,
- @SoftInputShowHideReason int reason) {
- final int uid = Binder.getCallingUid();
- final int callingUserId = UserHandle.getUserId(uid);
- final int userId = resolveImeUserIdLocked(callingUserId);
+ @SoftInputShowHideReason int reason, int uid, @UserIdInt int userId) {
if (!canInteractWithImeLocked(uid, client, "showSoftInput", statsToken,
userId)) {
ImeTracker.forLogging().onFailed(
@@ -3091,7 +3145,8 @@
try {
if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
if (Flags.refactorInsetsController()) {
- boolean wasVisible = mVisibilityStateComputer.isInputShown();
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
+ boolean wasVisible = visibilityStateComputer.isInputShown();
if (userData.mImeBindingState != null
&& userData.mImeBindingState.mFocusedWindowClient != null
&& userData.mImeBindingState.mFocusedWindowClient.mClient != null) {
@@ -3429,7 +3484,9 @@
@NonNull ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
@MotionEvent.ToolType int lastClickToolType, @Nullable ResultReceiver resultReceiver,
@SoftInputShowHideReason int reason, @UserIdInt int userId) {
- if (!mVisibilityStateComputer.onImeShowFlags(statsToken, flags)) {
+ final var userData = getUserData(userId);
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
+ if (!visibilityStateComputer.onImeShowFlags(statsToken, flags)) {
return false;
}
@@ -3439,10 +3496,9 @@
}
ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_SYSTEM_READY);
- mVisibilityStateComputer.requestImeVisibility(windowToken, true);
+ visibilityStateComputer.requestImeVisibility(windowToken, true);
// Ensure binding the connection when IME is going to show.
- final var userData = getUserData(userId);
final var bindingController = userData.mBindingController;
bindingController.setCurrentMethodVisible();
final IInputMethodInvoker curMethod = bindingController.getCurMethod();
@@ -3461,14 +3517,14 @@
userData.mCurStatsToken = null;
if (Flags.useHandwritingListenerForTooltype()) {
- maybeReportToolType();
+ maybeReportToolType(userId);
} else if (lastClickToolType != MotionEvent.TOOL_TYPE_UNKNOWN) {
- onUpdateEditorToolType(lastClickToolType);
+ onUpdateEditorToolTypeLocked(lastClickToolType, userId);
}
mVisibilityApplier.performShowIme(windowToken, statsToken,
- mVisibilityStateComputer.getShowFlagsForInputMethodServiceOnly(),
+ visibilityStateComputer.getShowFlagsForInputMethodServiceOnly(),
resultReceiver, reason, userId);
- mVisibilityStateComputer.setInputShown(true);
+ visibilityStateComputer.setInputShown(true);
return true;
} else {
ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
@@ -3478,7 +3534,8 @@
}
@GuardedBy("ImfLock.class")
- private void maybeReportToolType() {
+ private void maybeReportToolType(@UserIdInt int userId) {
+ // TODO(b/356638981): This needs to be compatible with visible background users.
int lastDeviceId = mInputManagerInternal.getLastUsedInputDeviceId();
final InputManager im = mContext.getSystemService(InputManager.class);
if (im == null) {
@@ -3497,7 +3554,7 @@
// other toolTypes are irrelevant and reported as unknown.
toolType = MotionEvent.TOOL_TYPE_UNKNOWN;
}
- onUpdateEditorToolType(toolType);
+ onUpdateEditorToolTypeLocked(toolType, userId);
}
@Override
@@ -3507,12 +3564,15 @@
ImeTracing.getInstance().triggerManagerServiceDump(
"InputMethodManagerService#hideSoftInput", mDumper);
synchronized (ImfLock.class) {
+ final int uid = Binder.getCallingUid();
+ final int callingUserId = UserHandle.getUserId(uid);
+ final int userId = resolveImeUserIdLocked(callingUserId);
final boolean result = hideSoftInputLocked(client, windowToken, statsToken, flags,
- resultReceiver, reason);
+ resultReceiver, reason, uid, userId);
// When ZeroJankProxy is enabled, the app has already received "true" as the return
// value, and expect "resultReceiver" to be notified later. See b/327751155.
if (!result && Flags.useZeroJankProxy()) {
- sendResultReceiverFailureLocked(resultReceiver);
+ sendResultReceiverFailureLocked(resultReceiver, userId);
}
return result; // ignored when ZeroJankProxy is enabled.
}
@@ -3521,12 +3581,12 @@
@GuardedBy("ImfLock.class")
private boolean hideSoftInputLocked(IInputMethodClient client, IBinder windowToken,
@NonNull ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags,
- ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
- final int uid = Binder.getCallingUid();
- final int callingUserId = UserHandle.getUserId(uid);
- final int userId = resolveImeUserIdLocked(callingUserId);
+ ResultReceiver resultReceiver, @SoftInputShowHideReason int reason,
+ int uid, @UserIdInt int userId) {
+ final var userData = getUserData(userId);
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
if (!canInteractWithImeLocked(uid, client, "hideSoftInput", statsToken, userId)) {
- if (mVisibilityStateComputer.isInputShown()) {
+ if (visibilityStateComputer.isInputShown()) {
ImeTracker.forLogging().onFailed(
statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
} else {
@@ -3535,7 +3595,6 @@
}
return false;
}
- final var userData = getUserData(userId);
final long ident = Binder.clearCallingIdentity();
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideSoftInput");
@@ -3544,7 +3603,7 @@
if (userData.mImeBindingState != null
&& userData.mImeBindingState.mFocusedWindowClient != null
&& userData.mImeBindingState.mFocusedWindowClient.mClient != null) {
- boolean wasVisible = mVisibilityStateComputer.isInputShown();
+ boolean wasVisible = visibilityStateComputer.isInputShown();
// TODO add windowToken to interface
userData.mImeBindingState.mFocusedWindowClient.mClient
.setImeVisibility(false, statsToken);
@@ -3592,7 +3651,8 @@
@SoftInputShowHideReason int reason, @UserIdInt int userId) {
final var userData = getUserData(userId);
final var bindingController = userData.mBindingController;
- if (!mVisibilityStateComputer.canHideIme(statsToken, flags)) {
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
+ if (!visibilityStateComputer.canHideIme(statsToken, flags)) {
return false;
}
@@ -3606,10 +3666,10 @@
// TODO(b/246309664): Clean up IMMS#mImeWindowVis
IInputMethodInvoker curMethod = bindingController.getCurMethod();
final boolean shouldHideSoftInput = curMethod != null
- && (mVisibilityStateComputer.isInputShown()
+ && (visibilityStateComputer.isInputShown()
|| (bindingController.getImeWindowVis() & InputMethodService.IME_ACTIVE) != 0);
- mVisibilityStateComputer.requestImeVisibility(windowToken, false);
+ visibilityStateComputer.requestImeVisibility(windowToken, false);
if (shouldHideSoftInput) {
// The IME will report its visible state again after the following message finally
// delivered to the IME process as an IPC. Hence the inconsistency between
@@ -3622,7 +3682,7 @@
ImeTracker.forLogging().onCancelled(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE);
}
bindingController.setCurrentMethodNotVisible();
- mVisibilityStateComputer.clearImeShowFlags();
+ visibilityStateComputer.clearImeShowFlags();
// Cancel existing statsToken for show IME as we got a hide request.
ImeTracker.forLogging().onCancelled(userData.mCurStatsToken,
ImeTracker.PHASE_SERVER_WAIT_IME);
@@ -3755,10 +3815,11 @@
// mShowForced flag when the next client's targetSdkVersion is T or higher.
final boolean shouldClearFlag =
mImePlatformCompatUtils.shouldClearShowForcedFlag(cs.mUid);
- final boolean showForced = mVisibilityStateComputer.mShowForced;
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
+ final boolean showForced = visibilityStateComputer.mShowForced;
if (userData.mImeBindingState.mFocusedWindow != windowToken
&& showForced && shouldClearFlag) {
- mVisibilityStateComputer.mShowForced = false;
+ visibilityStateComputer.mShowForced = false;
}
// Verify if caller is a background user.
@@ -3850,7 +3911,8 @@
final ImeTargetWindowState windowState = new ImeTargetWindowState(
softInputMode, windowFlags, !sameWindowFocused, isTextEditor,
startInputByWinGainedFocus, toolType);
- mVisibilityStateComputer.setWindowState(windowToken, windowState);
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
+ visibilityStateComputer.setWindowState(windowToken, windowState);
if (sameWindowFocused && isTextEditor) {
if (DEBUG) {
@@ -3881,7 +3943,7 @@
boolean didStart = false;
InputBindResult res = null;
- final ImeVisibilityResult imeVisRes = mVisibilityStateComputer.computeState(windowState,
+ final ImeVisibilityResult imeVisRes = visibilityStateComputer.computeState(windowState,
isSoftInputModeStateVisibleAllowed(unverifiedTargetSdkVersion, startInputFlags));
if (imeVisRes != null) {
boolean isShow = false;
@@ -4345,13 +4407,13 @@
+ subtype.getLocale() + ", " + subtype.getMode());
}
}
+ final var userData = getUserData(userId);
synchronized (ImfLock.class) {
if (!mSystemReady) {
return;
}
final var additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId);
- final boolean isCurrentUser = (mCurrentUserId == userId);
final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
final var newAdditionalSubtypeMap = settings.getNewAdditionalSubtypeMap(
imiId, toBeAdded, additionalSubtypeMap, mPackageManagerInternal, callingUid);
@@ -4360,14 +4422,12 @@
settings.getMethodMap());
final long ident = Binder.clearCallingIdentity();
try {
- final InputMethodSettings newSettings = queryInputMethodServicesInternal(
- mContext, userId, AdditionalSubtypeMapRepository.get(userId),
- DirectBootAwareness.AUTO);
+ final var methodMap = userData.mRawInputMethodMap.get().toInputMethodMap(
+ AdditionalSubtypeMapRepository.get(userId), DirectBootAwareness.AUTO,
+ mUserManagerInternal.isUserUnlockingOrUnlocked(userId));
+ final var newSettings = InputMethodSettings.create(methodMap, userId);
InputMethodSettingsRepository.put(userId, newSettings);
- if (isCurrentUser) {
- postInputMethodSettingUpdatedLocked(false /* resetDefaultEnabledIme */,
- userId);
- }
+ postInputMethodSettingUpdatedLocked(false /* resetDefaultEnabledIme */, userId);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -4395,17 +4455,14 @@
final long ident = Binder.clearCallingIdentity();
try {
synchronized (ImfLock.class) {
- final boolean currentUser = (mCurrentUserId == userId);
final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
if (!settings.setEnabledInputMethodSubtypes(imeId, subtypeHashCodes)) {
return;
}
- if (currentUser) {
- // To avoid unnecessary "updateInputMethodsFromSettingsLocked" from happening.
- final var userData = getUserData(userId);
- userData.mLastEnabledInputMethodsStr = settings.getEnabledInputMethodsStr();
- updateInputMethodsFromSettingsLocked(false /* enabledChanged */, userId);
- }
+ // To avoid unnecessary "updateInputMethodsFromSettingsLocked" from happening.
+ final var userData = getUserData(userId);
+ userData.mLastEnabledInputMethodsStr = settings.getEnabledInputMethodsStr();
+ updateInputMethodsFromSettingsLocked(false /* enabledChanged */, userId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -4710,20 +4767,21 @@
final int userId = mCurrentUserId;
final var userData = getUserData(userId);
final var bindingController = userData.mBindingController;
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
final long token = proto.start(fieldId);
proto.write(CUR_METHOD_ID, bindingController.getSelectedMethodId());
proto.write(CUR_SEQ, bindingController.getSequenceNumber());
proto.write(CUR_CLIENT, Objects.toString(userData.mCurClient));
userData.mImeBindingState.dumpDebug(proto, mWindowManagerInternal);
proto.write(LAST_IME_TARGET_WINDOW_NAME, mWindowManagerInternal.getWindowName(
- mVisibilityStateComputer.getLastImeTargetWindow()));
+ visibilityStateComputer.getLastImeTargetWindow()));
proto.write(CUR_FOCUSED_WINDOW_SOFT_INPUT_MODE, InputMethodDebug.softInputModeToString(
userData.mImeBindingState.mFocusedWindowSoftInputMode));
if (userData.mCurEditorInfo != null) {
userData.mCurEditorInfo.dumpDebug(proto, CUR_ATTRIBUTE);
}
proto.write(CUR_ID, bindingController.getCurId());
- mVisibilityStateComputer.dumpDebug(proto, fieldId);
+ visibilityStateComputer.dumpDebug(proto, fieldId);
proto.write(IN_FULLSCREEN_MODE, userData.mInFullscreenMode);
proto.write(CUR_TOKEN, Objects.toString(bindingController.getCurToken()));
proto.write(CUR_TOKEN_DISPLAY_ID, bindingController.getCurTokenDisplayId());
@@ -4778,7 +4836,8 @@
}
ImeTracker.forLogging().onProgress(statsToken,
ImeTracker.PHASE_SERVER_CURRENT_ACTIVE_IME);
- final IBinder requestToken = mVisibilityStateComputer.getWindowTokenFrom(
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
+ final IBinder requestToken = visibilityStateComputer.getWindowTokenFrom(
windowToken, userId);
mVisibilityApplier.applyImeVisibility(requestToken, statsToken,
setVisible ? STATE_SHOW_IME : STATE_HIDE_IME,
@@ -4843,9 +4902,10 @@
void onShowHideSoftInputRequested(boolean show, IBinder requestImeToken,
@SoftInputShowHideReason int reason, @Nullable ImeTracker.Token statsToken,
@UserIdInt int userId) {
- final IBinder requestToken = mVisibilityStateComputer.getWindowTokenFrom(requestImeToken,
- userId);
final var userData = getUserData(userId);
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
+ final IBinder requestToken = visibilityStateComputer.getWindowTokenFrom(requestImeToken,
+ userId);
final var bindingController = userData.mBindingController;
final WindowManagerInternal.ImeTargetInfo info =
mWindowManagerInternal.onToggleImeRequested(
@@ -4890,7 +4950,8 @@
.setImeVisibility(false, statsToken);
}
} else {
- hideCurrentInputLocked(mVisibilityStateComputer.getLastImeTargetWindow(),
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
+ hideCurrentInputLocked(visibilityStateComputer.getLastImeTargetWindow(),
statsToken, flags, null /* resultReceiver */, reason, userId);
}
} finally {
@@ -4929,7 +4990,8 @@
.setImeVisibility(true, statsToken);
}
} else {
- showCurrentInputLocked(mVisibilityStateComputer.getLastImeTargetWindow(),
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
+ showCurrentInputLocked(visibilityStateComputer.getLastImeTargetWindow(),
statsToken, flags, MotionEvent.TOOL_TYPE_UNKNOWN,
null /* resultReceiver */, reason, userId);
}
@@ -4950,8 +5012,8 @@
@GuardedBy("ImfLock.class")
void onApplyImeVisibilityFromComputerLocked(IBinder windowToken,
- @NonNull ImeTracker.Token statsToken, @NonNull ImeVisibilityResult result) {
- final int userId = resolveImeUserIdFromWindowLocked(windowToken);
+ @NonNull ImeTracker.Token statsToken, @NonNull ImeVisibilityResult result,
+ @UserIdInt int userId) {
mVisibilityApplier.applyImeVisibility(windowToken, statsToken, result.getState(),
result.getReason(), userId);
}
@@ -5017,8 +5079,11 @@
// This is undocumented so far, but IMM#showInputMethodPicker() has been
// implemented so that auxiliary subtypes will be excluded when the soft
// keyboard is invisible.
- case InputMethodManager.SHOW_IM_PICKER_MODE_AUTO ->
- showAuxSubtypes = mVisibilityStateComputer.isInputShown();
+ case InputMethodManager.SHOW_IM_PICKER_MODE_AUTO -> {
+ final var userData = getUserData(userId);
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
+ showAuxSubtypes = visibilityStateComputer.isInputShown();
+ }
case InputMethodManager.SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES ->
showAuxSubtypes = true;
case InputMethodManager.SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES ->
@@ -5069,7 +5134,7 @@
mMenuControllerNew.show(menuItems, selectedIndex, displayId, userId);
} else {
mMenuController.showInputMethodMenuLocked(showAuxSubtypes, displayId,
- lastInputMethodId, lastInputMethodSubtypeId, imList);
+ lastInputMethodId, lastInputMethodSubtypeId, imList, userId);
}
}
@@ -5266,7 +5331,8 @@
bindingController.getCurMethodUid())) {
// Handle IME visibility when interactive changed before finishing the input to
// ensure we preserve the last state as possible.
- final ImeVisibilityResult imeVisRes = mVisibilityStateComputer.onInteractiveChanged(
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
+ final ImeVisibilityResult imeVisRes = visibilityStateComputer.onInteractiveChanged(
userData.mImeBindingState.mFocusedWindow, interactive);
if (imeVisRes != null) {
// Pass in a null statsToken as the IME snapshot is not tracked by ImeTracker.
@@ -5301,31 +5367,15 @@
}
@NonNull
- static InputMethodSettings queryInputMethodServicesInternal(Context context,
- @UserIdInt int userId, @NonNull AdditionalSubtypeMap additionalSubtypeMap,
- @DirectBootAwareness int directBootAwareness) {
+ static RawInputMethodMap queryRawInputMethodServiceMap(Context context, @UserIdInt int userId) {
final Context userAwareContext = context.getUserId() == userId
? context
: context.createContextAsUser(UserHandle.of(userId), 0 /* flags */);
- final int directBootAwarenessFlags;
- switch (directBootAwareness) {
- case DirectBootAwareness.ANY:
- directBootAwarenessFlags = PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
- break;
- case DirectBootAwareness.AUTO:
- directBootAwarenessFlags = PackageManager.MATCH_DIRECT_BOOT_AUTO;
- break;
- default:
- directBootAwarenessFlags = PackageManager.MATCH_DIRECT_BOOT_AUTO;
- Slog.e(TAG, "Unknown directBootAwareness=" + directBootAwareness
- + ". Falling back to DirectBootAwareness.AUTO");
- break;
- }
final int flags = PackageManager.GET_META_DATA
| PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
- | directBootAwarenessFlags;
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
// Beware that package visibility filtering will be enforced based on the effective calling
// identity (Binder.getCallingUid()), but our use case always expect Binder.getCallingUid()
@@ -5341,14 +5391,11 @@
final List<String> enabledInputMethodList =
InputMethodUtils.getEnabledInputMethodIdsForFiltering(context, userId);
- final InputMethodMap methodMap = filterInputMethodServices(
- additionalSubtypeMap, enabledInputMethodList, userAwareContext, services);
- return InputMethodSettings.create(methodMap, userId);
+ return filterInputMethodServices(enabledInputMethodList, userAwareContext, services);
}
@NonNull
- static InputMethodMap filterInputMethodServices(
- @NonNull AdditionalSubtypeMap additionalSubtypeMap,
+ static RawInputMethodMap filterInputMethodServices(
List<String> enabledInputMethodList, Context userAwareContext,
List<ResolveInfo> services) {
final ArrayMap<String, Integer> imiPackageCount = new ArrayMap<>();
@@ -5369,7 +5416,7 @@
try {
final InputMethodInfo imi = new InputMethodInfo(userAwareContext, ri,
- additionalSubtypeMap.get(imeId));
+ Collections.emptyList());
if (imi.isVrOnly()) {
continue; // Skip VR-only IME, which isn't supported for now.
}
@@ -5392,7 +5439,7 @@
Slog.wtf(TAG, "Unable to load input method " + imeId, e);
}
}
- return InputMethodMap.of(methodMap);
+ return RawInputMethodMap.of(methodMap);
}
@GuardedBy("ImfLock.class")
@@ -5940,13 +5987,14 @@
// Hide the IME method menu only when the IME surface parent is changed by the
// input target changed, in case seeing the dialog dismiss flickering during
// the next focused window starting the input connection.
- if (mVisibilityStateComputer.getLastImeTargetWindow()
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
+ if (visibilityStateComputer.getLastImeTargetWindow()
!= userData.mImeBindingState.mFocusedWindow) {
if (mNewInputMethodSwitcherMenuEnabled) {
final var bindingController = getInputMethodBindingController(userId);
mMenuControllerNew.hide(bindingController.getCurTokenDisplayId(), userId);
} else {
- mMenuController.hideInputMethodMenuLocked();
+ mMenuController.hideInputMethodMenuLocked(userId);
}
}
}
@@ -6312,7 +6360,8 @@
method = bindingController.getCurMethod();
p.println(" mCurMethod=" + method);
p.println(" mEnabledSession=" + userData.mEnabledSession);
- mVisibilityStateComputer.dump(pw, " ");
+ final var visibilityStateComputer = userData.mVisibilityStateComputer;
+ visibilityStateComputer.dump(pw, " ");
p.println(" mInFullscreenMode=" + userData.mInFullscreenMode);
p.println(" mSystemReady=" + mSystemReady + " mInteractive=" + mIsInteractive);
p.println(" mConcurrentMultiUserModeEnabled=" + mConcurrentMultiUserModeEnabled);
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
index ba5c13e..f16a5a0 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
@@ -21,6 +21,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
@@ -77,13 +78,12 @@
@GuardedBy("ImfLock.class")
void showInputMethodMenuLocked(boolean showAuxSubtypes, int displayId,
String preferredInputMethodId, int preferredInputMethodSubtypeId,
- @NonNull List<ImeSubtypeListItem> imList) {
+ @NonNull List<ImeSubtypeListItem> imList, @UserIdInt int userId) {
if (DEBUG) Slog.v(TAG, "Show switching menu. showAuxSubtypes=" + showAuxSubtypes);
- final int userId = mService.getCurrentImeUserIdLocked();
final var bindingController = mService.getInputMethodBindingController(userId);
- hideInputMethodMenuLocked();
+ hideInputMethodMenuLocked(userId);
if (preferredInputMethodSubtypeId == NOT_A_SUBTYPE_ID) {
final InputMethodSubtype currentSubtype =
@@ -131,7 +131,7 @@
}
final Context dialogWindowContext = mDialogWindowContext.get(displayId);
mDialogBuilder = new AlertDialog.Builder(dialogWindowContext);
- mDialogBuilder.setOnCancelListener(dialog -> hideInputMethodMenu());
+ mDialogBuilder.setOnCancelListener(dialog -> hideInputMethodMenu(userId));
final Context dialogContext = mDialogBuilder.getContext();
final TypedArray a = dialogContext.obtainStyledAttributes(null,
@@ -162,7 +162,7 @@
isChecked, userId);
// Ensure that the input method dialog is dismissed when changing
// the hardware keyboard state.
- hideInputMethodMenu();
+ hideInputMethodMenu(userId);
});
// Fill the list items with onClick listener, which takes care of IME (and subtype)
@@ -185,7 +185,7 @@
}
mService.setInputMethodLocked(im.getId(), subtypeId, userId);
}
- hideInputMethodMenuLocked();
+ hideInputMethodMenuLocked(userId);
}
};
mDialogBuilder.setSingleChoiceItems(adapter, checkedItem, choiceListener);
@@ -209,10 +209,10 @@
mSwitchingDialog.show();
}
- void updateKeyboardFromSettingsLocked() {
+ void updateKeyboardFromSettingsLocked(@UserIdInt int userId) {
mShowImeWithHardKeyboard =
SecureSettingsWrapper.getBoolean(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
- false, mService.getCurrentImeUserIdLocked());
+ false, userId);
if (mSwitchingDialog != null && mSwitchingDialogTitleView != null
&& mSwitchingDialog.isShowing()) {
final Switch hardKeySwitch = mSwitchingDialogTitleView.findViewById(
@@ -223,18 +223,22 @@
/**
* Hides the input method switcher menu.
+ *
+ * @param userId user ID for this operation
*/
- void hideInputMethodMenu() {
+ void hideInputMethodMenu(@UserIdInt int userId) {
synchronized (ImfLock.class) {
- hideInputMethodMenuLocked();
+ hideInputMethodMenuLocked(userId);
}
}
/**
* Hides the input method switcher menu, synchronised version of {@link #hideInputMethodMenu}.
+ *
+ * @param userId user ID for this operation
*/
@GuardedBy("ImfLock.class")
- void hideInputMethodMenuLocked() {
+ void hideInputMethodMenuLocked(@UserIdInt int userId) {
if (DEBUG) Slog.v(TAG, "Hide switching menu");
if (mSwitchingDialog != null) {
@@ -242,8 +246,6 @@
mSwitchingDialog = null;
mSwitchingDialogTitleView = null;
- // TODO(b/305849394): Make InputMethodMenuController multi-user aware
- final int userId = mService.getCurrentImeUserIdLocked();
mService.updateSystemUiLocked(userId);
mService.sendOnNavButtonFlagsChangedToAllImesLocked();
mDialogBuilder = null;
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodMenuControllerNew.java b/services/core/java/com/android/server/inputmethod/InputMethodMenuControllerNew.java
index 045414b..b72a34d 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodMenuControllerNew.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodMenuControllerNew.java
@@ -135,11 +135,13 @@
final RecyclerView recyclerView = contentView
.requireViewById(com.android.internal.R.id.list);
recyclerView.setAdapter(new Adapter(items, selectedIndex, inflater, onClickListener));
- // Scroll to the currently selected IME.
- recyclerView.scrollToPosition(selectedIndex);
+ // Scroll to the currently selected IME. This must run after the recycler view is laid out.
+ recyclerView.post(() -> recyclerView.scrollToPosition(selectedIndex));
// Indicate that the list can be scrolled.
recyclerView.setScrollIndicators(
hasLanguageSettingsButton ? View.SCROLL_INDICATOR_BOTTOM : 0);
+ // Request focus to enable rotary scrolling on watches.
+ recyclerView.requestFocus();
builder.setOnCancelListener(dialog -> hide(displayId, userId));
mMenuItems = items;
diff --git a/services/core/java/com/android/server/inputmethod/RawInputMethodMap.java b/services/core/java/com/android/server/inputmethod/RawInputMethodMap.java
new file mode 100644
index 0000000..4e39a3f
--- /dev/null
+++ b/services/core/java/com/android/server/inputmethod/RawInputMethodMap.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.inputmethod;
+
+import android.annotation.AnyThread;
+import android.annotation.NonNull;
+import android.util.ArrayMap;
+import android.util.Slog;
+import android.view.inputmethod.InputMethodInfo;
+
+import com.android.internal.inputmethod.DirectBootAwareness;
+
+import java.util.List;
+
+/**
+ * This is quite similar to {@link InputMethodMap} with two major differences.
+ *
+ * <ul>
+ * <li>Additional {@link android.view.inputmethod.InputMethodSubtype} is not included.</li>
+ * <li>Always include direct-boot unaware {@link android.inputmethodservice.InputMethodService}.
+ * </li>
+ * </ul>
+ *
+ * <p>As seen in {@link #toInputMethodMap(AdditionalSubtypeMap, int, boolean)}, you can consider
+ * this is a prototype data where you can always derive {@link InputMethodMap} with
+ * {@link AdditionalSubtypeMap} and a boolean information whether
+ * {@link com.android.server.pm.UserManagerInternal#isUserUnlockingOrUnlocked(int)} returns
+ * {@code true} or not.</p>
+ */
+final class RawInputMethodMap {
+ static final String TAG = "RawInputMethodMap";
+
+ private static final ArrayMap<String, InputMethodInfo> EMPTY_MAP = new ArrayMap<>();
+
+ private final ArrayMap<String, InputMethodInfo> mMap;
+
+ static RawInputMethodMap emptyMap() {
+ return new RawInputMethodMap(EMPTY_MAP);
+ }
+
+ static RawInputMethodMap of(@NonNull ArrayMap<String, InputMethodInfo> map) {
+ return new RawInputMethodMap(map);
+ }
+
+ private RawInputMethodMap(@NonNull ArrayMap<String, InputMethodInfo> map) {
+ mMap = map.isEmpty() ? EMPTY_MAP : new ArrayMap<>(map);
+ }
+
+ @AnyThread
+ @NonNull
+ List<InputMethodInfo> values() {
+ return List.copyOf(mMap.values());
+ }
+
+ @NonNull
+ InputMethodMap toInputMethodMap(@NonNull AdditionalSubtypeMap additionalSubtypeMap,
+ @DirectBootAwareness int directBootAwareness, boolean userUnlocked) {
+ final int size = mMap.size();
+ final var newMap = new ArrayMap<String, InputMethodInfo>(size);
+
+ final boolean requireDirectBootAwareFlag;
+ switch (directBootAwareness) {
+ case DirectBootAwareness.ANY -> requireDirectBootAwareFlag = false;
+ case DirectBootAwareness.AUTO -> requireDirectBootAwareFlag = !userUnlocked;
+ default -> {
+ requireDirectBootAwareFlag = !userUnlocked;
+ Slog.e(TAG, "Unknown directBootAwareness=" + directBootAwareness
+ + ". Falling back to DirectBootAwareness.AUTO");
+ }
+ }
+
+ boolean updated = false;
+ for (int i = 0; i < size; ++i) {
+ final var imeId = mMap.keyAt(i);
+ final var imi = mMap.valueAt(i);
+ if (requireDirectBootAwareFlag && !imi.getServiceInfo().directBootAware) {
+ updated = true;
+ continue;
+ }
+ final var newAdditionalSubtypes = additionalSubtypeMap.get(imeId);
+ if (newAdditionalSubtypes == null || newAdditionalSubtypes.isEmpty()) {
+ newMap.put(imi.getId(), imi);
+ } else {
+ updated = true;
+ newMap.put(imi.getId(), new InputMethodInfo(imi, newAdditionalSubtypes));
+ }
+ }
+ // If newMap is semantically the same as mMap, we can reuse mMap and discard newMap.
+ return InputMethodMap.of(updated ? newMap : mMap);
+ }
+}
diff --git a/services/core/java/com/android/server/inputmethod/SecureSettingsWrapper.java b/services/core/java/com/android/server/inputmethod/SecureSettingsWrapper.java
index 476888e..3beec09 100644
--- a/services/core/java/com/android/server/inputmethod/SecureSettingsWrapper.java
+++ b/services/core/java/com/android/server/inputmethod/SecureSettingsWrapper.java
@@ -20,10 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
-import android.app.ActivityManagerInternal;
import android.content.ContentResolver;
-import android.content.Context;
-import android.content.pm.UserInfo;
import android.provider.Settings;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -321,30 +318,13 @@
}
/**
- * Called when {@link InputMethodManagerService} is starting.
+ * Called when the system is starting.
*
- * @param context the {@link Context} to be used.
+ * @param contentResolver the {@link ContentResolver} to be used
*/
@AnyThread
- static void onStart(@NonNull Context context) {
- sContentResolver = context.getContentResolver();
-
- final int userId = LocalServices.getService(ActivityManagerInternal.class)
- .getCurrentUserId();
- final UserManagerInternal userManagerInternal =
- LocalServices.getService(UserManagerInternal.class);
- putOrGet(userId, createImpl(userManagerInternal, userId));
-
- userManagerInternal.addUserLifecycleListener(
- new UserManagerInternal.UserLifecycleListener() {
- @Override
- public void onUserRemoved(UserInfo user) {
- synchronized (sMutationLock) {
- sUserMap = sUserMap.cloneWithRemoveOrSelf(user.id);
- }
- }
- }
- );
+ static void setContentResolver(@NonNull ContentResolver contentResolver) {
+ sContentResolver = contentResolver;
}
/**
@@ -394,6 +374,18 @@
}
/**
+ * Called when a user is being removed.
+ *
+ * @param userId the ID of the user whose storage is being removed
+ */
+ @AnyThread
+ static void onUserRemoved(@UserIdInt int userId) {
+ synchronized (sMutationLock) {
+ sUserMap = sUserMap.cloneWithRemoveOrSelf(userId);
+ }
+ }
+
+ /**
* Put the given string {@code value} to {@code key}.
*
* @param key a secure settings key.
diff --git a/services/core/java/com/android/server/inputmethod/UserData.java b/services/core/java/com/android/server/inputmethod/UserData.java
index be57321..28394c6a 100644
--- a/services/core/java/com/android/server/inputmethod/UserData.java
+++ b/services/core/java/com/android/server/inputmethod/UserData.java
@@ -30,6 +30,7 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
/** Placeholder for all IMMS user specific fields */
final class UserData {
@@ -43,6 +44,17 @@
@NonNull
final CountDownLatch mBackgroundLoadLatch = new CountDownLatch(1);
+ /**
+ * Contains non-null {@link RawInputMethodMap}, which represents the latest collections of
+ * {@link android.view.inputmethod.InputMethodInfo} for both direct-boot aware and unaware IMEs
+ * before taking {@link AdditionalSubtypeMap} into account.
+ *
+ * <p>See {@link RawInputMethodMap} for details on when to use this.</p>
+ */
+ @NonNull
+ final AtomicReference<RawInputMethodMap> mRawInputMethodMap =
+ new AtomicReference<>(RawInputMethodMap.emptyMap());
+
@NonNull
final InputMethodBindingController mBindingController;
@@ -54,6 +66,9 @@
final HardwareKeyboardShortcutController mHardwareKeyboardShortcutController =
new HardwareKeyboardShortcutController();
+ @NonNull
+ final ImeVisibilityStateComputer mVisibilityStateComputer;
+
/**
* Have we called mCurMethod.bindInput()?
*/
@@ -143,9 +158,11 @@
* Intended to be instantiated only from this file.
*/
UserData(@UserIdInt int userId,
- @NonNull InputMethodBindingController bindingController) {
+ @NonNull InputMethodBindingController bindingController,
+ @NonNull ImeVisibilityStateComputer stateComputer) {
mUserId = userId;
mBindingController = bindingController;
+ mVisibilityStateComputer = stateComputer;
}
@Override
diff --git a/services/core/java/com/android/server/inputmethod/UserDataRepository.java b/services/core/java/com/android/server/inputmethod/UserDataRepository.java
index e3524b1..39f580c 100644
--- a/services/core/java/com/android/server/inputmethod/UserDataRepository.java
+++ b/services/core/java/com/android/server/inputmethod/UserDataRepository.java
@@ -30,7 +30,10 @@
@NonNull
private volatile ImmutableSparseArray<UserData> mUserData = ImmutableSparseArray.empty();
+ @NonNull
private final IntFunction<InputMethodBindingController> mBindingControllerFactory;
+ @NonNull
+ private final IntFunction<ImeVisibilityStateComputer> mVisibilityStateComputerFactory;
@AnyThread
@NonNull
@@ -42,7 +45,8 @@
}
// Note that the below line can be called concurrently. Here we assume that
// instantiating UserData for the same user multiple times would have no side effect.
- final var newUserData = new UserData(userId, mBindingControllerFactory.apply(userId));
+ final var newUserData = new UserData(userId, mBindingControllerFactory.apply(userId),
+ mVisibilityStateComputerFactory.apply(userId));
synchronized (mMutationLock) {
mUserData = mUserData.cloneWithPutOrSelf(userId, newUserData);
return newUserData;
@@ -54,9 +58,10 @@
mUserData.forEach(consumer);
}
- UserDataRepository(
- @NonNull IntFunction<InputMethodBindingController> bindingControllerFactory) {
+ UserDataRepository(@NonNull IntFunction<InputMethodBindingController> bindingControllerFactory,
+ @NonNull IntFunction<ImeVisibilityStateComputer> visibilityStateComputerFactory) {
mBindingControllerFactory = bindingControllerFactory;
+ mVisibilityStateComputerFactory = visibilityStateComputerFactory;
}
@AnyThread
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubTransactionManager.java b/services/core/java/com/android/server/location/contexthub/ContextHubTransactionManager.java
index cd69eba..2a0b1af 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubTransactionManager.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubTransactionManager.java
@@ -717,9 +717,13 @@
}
mReliableMessageHostEndpointIdActiveSet.remove(transaction.getHostEndpointId());
- Log.d(TAG, "Successfully completed reliable message transaction with "
- + "message sequence number: " + transaction.getMessageSequenceNumber()
- + " and result: " + result);
+ Log.d(
+ TAG,
+ "Successfully completed reliable message transaction with "
+ + "message sequence number = "
+ + transaction.getMessageSequenceNumber()
+ + " and result = "
+ + result);
}
/**
@@ -732,15 +736,20 @@
int numCompletedStartCalls = transaction.getNumCompletedStartCalls();
@ContextHubTransaction.Result int result = transaction.onTransact();
if (result == ContextHubTransaction.RESULT_SUCCESS) {
- Log.d(TAG, "Successfully "
- + (numCompletedStartCalls == 0 ? "started" : "retried")
- + " reliable message transaction with message sequence number: "
- + transaction.getMessageSequenceNumber());
+ Log.d(
+ TAG,
+ "Successfully "
+ + (numCompletedStartCalls == 0 ? "started" : "retried")
+ + " reliable message transaction with message sequence number = "
+ + transaction.getMessageSequenceNumber());
} else {
- Log.w(TAG, "Could not start reliable message transaction with "
- + "message sequence number: "
- + transaction.getMessageSequenceNumber()
- + ", result: " + result);
+ Log.w(
+ TAG,
+ "Could not start reliable message transaction with "
+ + "message sequence number = "
+ + transaction.getMessageSequenceNumber()
+ + ", result = "
+ + result);
}
transaction.setNextRetryTime(now + RELIABLE_MESSAGE_RETRY_WAIT_TIME.toNanos());
diff --git a/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java b/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java
index 5df0de8..df45a6e 100644
--- a/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java
+++ b/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java
@@ -77,7 +77,7 @@
mIsInEmergencyCall = mTelephonyManager.isEmergencyNumber(
intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER));
dispatchEmergencyStateChanged();
- } catch (IllegalStateException e) {
+ } catch (IllegalStateException | UnsupportedOperationException e) {
Log.w(TAG, "Failed to call TelephonyManager.isEmergencyNumber().", e);
}
}
diff --git a/services/core/java/com/android/server/net/Android.bp b/services/core/java/com/android/server/net/Android.bp
index 3ac2d23..68dc781 100644
--- a/services/core/java/com/android/server/net/Android.bp
+++ b/services/core/java/com/android/server/net/Android.bp
@@ -9,3 +9,10 @@
name: "net_flags_lib",
aconfig_declarations: "net_flags",
}
+
+java_aconfig_library {
+ name: "net_flags_host_lib",
+ aconfig_declarations: "net_flags",
+ host_supported: true,
+ mode: "test",
+}
diff --git a/services/core/java/com/android/server/notification/NotificationAttentionHelper.java b/services/core/java/com/android/server/notification/NotificationAttentionHelper.java
index 5a9cf03..bd551fb 100644
--- a/services/core/java/com/android/server/notification/NotificationAttentionHelper.java
+++ b/services/core/java/com/android/server/notification/NotificationAttentionHelper.java
@@ -230,9 +230,17 @@
mFlagResolver.getIntValue(NotificationFlags.NOTIF_VOLUME1),
mFlagResolver.getIntValue(NotificationFlags.NOTIF_VOLUME2),
mFlagResolver.getIntValue(NotificationFlags.NOTIF_COOLDOWN_COUNTER_RESET),
- record -> mPackageManager.checkPermission(
+ record -> {
+ final String category = record.getNotification().category;
+ if (Notification.CATEGORY_ALARM.equals(category)
+ || Notification.CATEGORY_CAR_EMERGENCY.equals(category)
+ || Notification.CATEGORY_CAR_WARNING.equals(category)) {
+ return true;
+ }
+ return mPackageManager.checkPermission(
permission.RECEIVE_EMERGENCY_BROADCAST,
- record.getSbn().getPackageName()) == PERMISSION_GRANTED);
+ record.getSbn().getPackageName()) == PERMISSION_GRANTED;
+ });
return new StrategyAvalanche(
mFlagResolver.getIntValue(NotificationFlags.NOTIF_COOLDOWN_T1),
@@ -248,9 +256,17 @@
mFlagResolver.getIntValue(NotificationFlags.NOTIF_VOLUME1),
mFlagResolver.getIntValue(NotificationFlags.NOTIF_VOLUME2),
mFlagResolver.getIntValue(NotificationFlags.NOTIF_COOLDOWN_COUNTER_RESET),
- record -> mPackageManager.checkPermission(
+ record -> {
+ final String category = record.getNotification().category;
+ if (Notification.CATEGORY_ALARM.equals(category)
+ || Notification.CATEGORY_CAR_EMERGENCY.equals(category)
+ || Notification.CATEGORY_CAR_WARNING.equals(category)) {
+ return true;
+ }
+ return mPackageManager.checkPermission(
permission.RECEIVE_EMERGENCY_BROADCAST,
- record.getSbn().getPackageName()) == PERMISSION_GRANTED);
+ record.getSbn().getPackageName()) == PERMISSION_GRANTED;
+ });
}
}
diff --git a/services/core/java/com/android/server/pm/BackgroundUserSoundNotifier.java b/services/core/java/com/android/server/pm/BackgroundUserSoundNotifier.java
index 15e758c..e3061a7 100644
--- a/services/core/java/com/android/server/pm/BackgroundUserSoundNotifier.java
+++ b/services/core/java/com/android/server/pm/BackgroundUserSoundNotifier.java
@@ -233,19 +233,25 @@
final Notification.Action switchUser = new Notification.Action.Builder(null,
fgContext.getString(R.string.bg_user_sound_notification_button_switch_user),
switchIntent).build();
- return new Notification.Builder(mSystemUserContext, BUSN_CHANNEL_ID)
+ Notification.Builder notificationBuilder = new Notification.Builder(mSystemUserContext,
+ BUSN_CHANNEL_ID)
.setSmallIcon(icon)
.setTicker(title)
+ .setCategory(Notification.CATEGORY_REMINDER)
.setWhen(0)
.setOngoing(true)
.setColor(fgContext.getColor(R.color.system_notification_accent_color))
.setContentTitle(title)
.setContentIntent(muteIntent)
.setAutoCancel(true)
- .setActions(mute, switchUser)
- .setContentText(fgContext.getString(R.string.bg_user_sound_notification_message))
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .build();
+ .setVisibility(Notification.VISIBILITY_PUBLIC);
+ if (mUserManager.isUserSwitcherEnabled() && (mUserManager.getUserSwitchability(
+ UserHandle.of(fgContext.getUserId())) == UserManager.SWITCHABILITY_STATUS_OK)) {
+ notificationBuilder.setActions(mute, switchUser);
+ } else {
+ notificationBuilder.setActions(mute);
+ }
+ return notificationBuilder.build();
}
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index f615ca1d..7156795 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -693,13 +693,18 @@
params.appLabel = TextUtils.trimToSize(params.appLabel,
PackageItemInfo.MAX_SAFE_LABEL_LENGTH);
- // Validate installer package name.
+ // Validate requested installer package name.
if (params.installerPackageName != null && !isValidPackageName(
params.installerPackageName)) {
params.installerPackageName = null;
}
- var requestedInstallerPackageName =
+ // Validate installer package name.
+ if (installerPackageName != null && !isValidPackageName(installerPackageName)) {
+ installerPackageName = null;
+ }
+
+ String requestedInstallerPackageName =
params.installerPackageName != null ? params.installerPackageName
: installerPackageName;
diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java
index 0e7ce2e..14b0fc8 100644
--- a/services/core/java/com/android/server/pm/UserManagerInternal.java
+++ b/services/core/java/com/android/server/pm/UserManagerInternal.java
@@ -497,6 +497,17 @@
public abstract boolean isUserVisible(@UserIdInt int userId, int displayId);
/**
+ * Checks if the given user is a visible background full user, which is a full background user
+ * assigned to secondary displays on the devices that have
+ * {@link UserManager#isVisibleBackgroundUsersEnabled()
+ * config_multiuserVisibleBackgroundUsers enabled} (for example, passenger users on
+ * automotive builds, using the display associated with their seats).
+ *
+ * @see UserManager#isUserVisible()
+ */
+ public abstract boolean isVisibleBackgroundFullUser(@UserIdInt int userId);
+
+ /**
* Returns the main display id assigned to the user, or {@code Display.INVALID_DISPLAY} if the
* user is not assigned to any main display.
*
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index dde9943..c902fb2 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -7927,6 +7927,17 @@
}
@Override
+ public boolean isVisibleBackgroundFullUser(@UserIdInt int userId) {
+ if (!UserManager.isVisibleBackgroundUsersEnabled()) {
+ return false;
+ }
+ boolean isForeground = userId == getCurrentUserId();
+ boolean isProfile = isProfileUnchecked(userId);
+ boolean isVisible = isUserVisible(userId);
+ return isVisible && !isForeground && !isProfile;
+ }
+
+ @Override
public int getMainDisplayAssignedToUser(@UserIdInt int userId) {
return mUserVisibilityMediator.getMainDisplayAssignedToUser(userId);
}
diff --git a/services/core/java/com/android/server/policy/ModifierShortcutManager.java b/services/core/java/com/android/server/policy/ModifierShortcutManager.java
index 40b2ff9..cefecbc 100644
--- a/services/core/java/com/android/server/policy/ModifierShortcutManager.java
+++ b/services/core/java/com/android/server/policy/ModifierShortcutManager.java
@@ -34,6 +34,7 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.text.TextUtils;
+import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.Slog;
@@ -55,6 +56,7 @@
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -705,4 +707,61 @@
}
return context.getString(resid);
};
+
+ void dump(String prefix, PrintWriter pw) {
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", prefix);
+ ipw.println("ModifierShortcutManager shortcuts:");
+
+ ipw.increaseIndent();
+ ipw.println("Roles");
+ ipw.increaseIndent();
+ for (int i = 0; i < mRoleShortcuts.size(); i++) {
+ String role = mRoleShortcuts.valueAt(i);
+ char shortcutChar = (char) mRoleShortcuts.keyAt(i);
+ Intent intent = getRoleLaunchIntent(role);
+ ipw.println(shortcutChar + " " + role + " " + intent);
+ }
+
+ for (int i = 0; i < mShiftRoleShortcuts.size(); i++) {
+ String role = mShiftRoleShortcuts.valueAt(i);
+ char shortcutChar = (char) mShiftRoleShortcuts.keyAt(i);
+ Intent intent = getRoleLaunchIntent(role);
+ ipw.println("SHIFT+" + shortcutChar + " " + role + " " + intent);
+ }
+
+ ipw.decreaseIndent();
+ ipw.println("Selectors");
+ ipw.increaseIndent();
+ for (int i = 0; i < mIntentShortcuts.size(); i++) {
+ char shortcutChar = (char) mIntentShortcuts.keyAt(i);
+ Intent intent = mIntentShortcuts.valueAt(i);
+ ipw.println(shortcutChar + " " + intent);
+ }
+
+ for (int i = 0; i < mShiftShortcuts.size(); i++) {
+ char shortcutChar = (char) mShiftShortcuts.keyAt(i);
+ Intent intent = mShiftShortcuts.valueAt(i);
+ ipw.println("SHIFT+" + shortcutChar + " " + intent);
+
+ }
+
+ if (modifierShortcutManagerMultiuser()) {
+ ipw.decreaseIndent();
+ ipw.println("ComponentNames");
+ ipw.increaseIndent();
+ for (int i = 0; i < mComponentShortcuts.size(); i++) {
+ char shortcutChar = (char) mComponentShortcuts.keyAt(i);
+ ComponentName component = mComponentShortcuts.valueAt(i);
+ Intent intent = resolveComponentNameIntent(component);
+ ipw.println(shortcutChar + " " + component + " " + intent);
+ }
+
+ for (int i = 0; i < mShiftComponentShortcuts.size(); i++) {
+ char shortcutChar = (char) mShiftComponentShortcuts.keyAt(i);
+ ComponentName component = mShiftComponentShortcuts.valueAt(i);
+ Intent intent = resolveComponentNameIntent(component);
+ ipw.println("SHIFT+" + shortcutChar + " " + component + " " + intent);
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index d0706d2..21d6c64 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -76,6 +76,7 @@
import static android.view.contentprotection.flags.Flags.createAccessibilityOverlayAppOpEnabled;
import static com.android.hardware.input.Flags.emojiAndScreenshotKeycodesAvailable;
+import static com.android.hardware.input.Flags.modifierShortcutDump;
import static com.android.server.flags.Flags.modifierShortcutManagerMultiuser;
import static com.android.server.flags.Flags.newBugreportKeyboardShortcut;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_KEYCHORD_DELAY;
@@ -2724,11 +2725,16 @@
@Override
void onLongPress(long eventTime) {
- // Long-press should be triggered only if app doesn't handle it.
- mDeferredKeyActionExecutor.queueKeyAction(
- KeyEvent.KEYCODE_STEM_PRIMARY,
- eventTime,
- () -> stemPrimaryLongPress(eventTime));
+ if (mLongPressOnStemPrimaryBehavior == LONG_PRESS_PRIMARY_LAUNCH_VOICE_ASSISTANT) {
+ // Long-press to assistant gesture is not overridable by apps.
+ stemPrimaryLongPress(eventTime);
+ } else {
+ // Other long-press actions should be triggered only if app doesn't handle it.
+ mDeferredKeyActionExecutor.queueKeyAction(
+ KeyEvent.KEYCODE_STEM_PRIMARY,
+ eventTime,
+ () -> stemPrimaryLongPress(eventTime));
+ }
}
@Override
@@ -6663,6 +6669,9 @@
pw.print(prefix); pw.println("Looper state:");
mHandler.getLooper().dump(new PrintWriterPrinter(pw), prefix + " ");
+ if (modifierShortcutDump()) {
+ mModifierShortcutManager.dump(prefix, pw);
+ }
}
private static String endcallBehaviorToString(int behavior) {
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index aa5f5a24..b28da55b 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -375,9 +375,9 @@
final boolean unimportantForLogging = newOwnerUid == Process.SYSTEM_UID
&& (newFlags & PowerManager.UNIMPORTANT_FOR_LOGGING) != 0;
try {
- mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag, historyTag,
- monitorType, newWorkSource, newOwnerPid, newTag, newHistoryTag,
- newMonitorType, unimportantForLogging);
+ notifyWakelockChanging(workSource, ownerPid, tag,
+ historyTag, monitorType, newWorkSource, newOwnerPid, newTag,
+ newHistoryTag, newMonitorType, unimportantForLogging);
} catch (RemoteException ex) {
// Ignore
}
@@ -1127,6 +1127,29 @@
mWakeLockLog.onWakeLockReleased(tag, ownerUid, currentTime);
}
+ @SuppressLint("AndroidFrameworkRequiresPermission")
+ private void notifyWakelockChanging(WorkSource workSource, int ownerPid, String tag,
+ String historyTag, int monitorType, WorkSource newWorkSource, int newOwnerPid,
+ String newTag, String newHistoryTag, int newMonitorType, boolean unimportantForLogging)
+ throws RemoteException {
+ if (!mFlags.improveWakelockLatency()) {
+ mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag,
+ historyTag, monitorType, newWorkSource, newOwnerPid, newTag,
+ newHistoryTag, newMonitorType, unimportantForLogging);
+ } else {
+ mHandler.post(() -> {
+ try {
+ mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag,
+ historyTag, monitorType, newWorkSource, newOwnerPid, newTag,
+ newHistoryTag, newMonitorType, unimportantForLogging);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to notify the wakelock changing from source via "
+ + "Notifier." + e.getLocalizedMessage());
+ }
+ });
+ }
+ }
+
private final class NotifierHandler extends Handler {
public NotifierHandler(Looper looper) {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 10faf14..699c9b5 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -34,6 +34,9 @@
import static com.android.internal.util.LatencyTracker.ACTION_TURN_ON_SCREEN;
import static com.android.server.deviceidle.Flags.disableWakelocksInLightIdle;
import static com.android.server.display.DisplayDeviceConfig.INVALID_BRIGHTNESS_IN_CONFIG;
+import static com.android.server.display.brightness.BrightnessUtils.isValidBrightnessValue;
+import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_UNKNOWN;
+import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_WAKE_LOCK_DEATH;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -650,11 +653,16 @@
private int mDozeScreenStateOverrideReasonFromDreamManager = Display.STATE_REASON_UNKNOWN;
- // The screen brightness to use while dozing.
+ // The screen brightness between 1 and 255 to use while dozing.
private int mDozeScreenBrightnessOverrideFromDreamManager = PowerManager.BRIGHTNESS_DEFAULT;
+ /**
+ * The screen brightness between {@link PowerManager#BRIGHTNESS_MIN} and
+ * {@link PowerManager.BRIGHTNESS_MAX} to use while dozing.
+ */
private float mDozeScreenBrightnessOverrideFromDreamManagerFloat =
PowerManager.BRIGHTNESS_INVALID_FLOAT;
+
// Keep display state when dozing.
private boolean mDrawWakeLockOverrideFromSidekick;
@@ -1819,7 +1827,7 @@
return;
}
- removeWakeLockLocked(wakeLock, index);
+ removeWakeLockDeathLocked(wakeLock, index);
}
}
@@ -1851,6 +1859,12 @@
}
@GuardedBy("mLock")
+ private void removeWakeLockDeathLocked(WakeLock wakeLock, int index) {
+ removeWakeLockNoUpdateLocked(wakeLock, index, RELEASE_REASON_WAKE_LOCK_DEATH);
+ updatePowerStateLocked();
+ }
+
+ @GuardedBy("mLock")
private void applyWakeLockFlagsOnReleaseLocked(WakeLock wakeLock) {
if ((wakeLock.mFlags & PowerManager.ON_AFTER_RELEASE) != 0
&& isScreenLock(wakeLock)) {
@@ -2005,7 +2019,7 @@
@GuardedBy("mLock")
private void notifyWakeLockReleasedLocked(WakeLock wakeLock) {
- notifyWakeLockReleasedLocked(wakeLock, ScreenTimeoutOverridePolicy.RELEASE_REASON_UNKNOWN);
+ notifyWakeLockReleasedLocked(wakeLock, RELEASE_REASON_UNKNOWN);
}
@GuardedBy("mLock")
@@ -4455,15 +4469,21 @@
}
private void setDozeOverrideFromDreamManagerInternal(
- int screenState, @Display.StateReason int reason, int screenBrightness) {
+ int screenState, @Display.StateReason int reason, float screenBrightnessFloat,
+ int screenBrightnessInt) {
synchronized (mLock) {
if (mDozeScreenStateOverrideFromDreamManager != screenState
- || mDozeScreenBrightnessOverrideFromDreamManager != screenBrightness) {
+ || mDozeScreenBrightnessOverrideFromDreamManager != screenBrightnessInt
+ || !BrightnessSynchronizer.floatEquals(
+ mDozeScreenBrightnessOverrideFromDreamManagerFloat,
+ screenBrightnessFloat)) {
mDozeScreenStateOverrideFromDreamManager = screenState;
mDozeScreenStateOverrideReasonFromDreamManager = reason;
- mDozeScreenBrightnessOverrideFromDreamManager = screenBrightness;
+ mDozeScreenBrightnessOverrideFromDreamManager = screenBrightnessInt;
mDozeScreenBrightnessOverrideFromDreamManagerFloat =
- BrightnessSynchronizer.brightnessIntToFloat(mDozeScreenBrightnessOverrideFromDreamManager);
+ isValidBrightnessValue(screenBrightnessFloat)
+ ? screenBrightnessFloat
+ : BrightnessSynchronizer.brightnessIntToFloat(screenBrightnessInt);
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
}
@@ -7095,7 +7115,7 @@
@Override
public void setDozeOverrideFromDreamManager(
- int screenState, int reason, int screenBrightness) {
+ int screenState, int reason, float screenBrightnessFloat, int screenBrightnessInt) {
switch (screenState) {
case Display.STATE_UNKNOWN:
case Display.STATE_OFF:
@@ -7108,11 +7128,17 @@
screenState = Display.STATE_UNKNOWN;
break;
}
- if (screenBrightness < PowerManager.BRIGHTNESS_DEFAULT
- || screenBrightness > PowerManager.BRIGHTNESS_ON) {
- screenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
+ if (screenBrightnessInt < PowerManager.BRIGHTNESS_DEFAULT
+ || screenBrightnessInt > PowerManager.BRIGHTNESS_ON) {
+ screenBrightnessInt = PowerManager.BRIGHTNESS_DEFAULT;
}
- setDozeOverrideFromDreamManagerInternal(screenState, reason, screenBrightness);
+ if (screenBrightnessFloat != PowerManager.BRIGHTNESS_OFF_FLOAT
+ && (screenBrightnessFloat < PowerManager.BRIGHTNESS_MIN
+ || screenBrightnessFloat > PowerManager.BRIGHTNESS_MAX)) {
+ screenBrightnessFloat = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+ }
+ setDozeOverrideFromDreamManagerInternal(screenState, reason, screenBrightnessFloat,
+ screenBrightnessInt);
}
@Override
diff --git a/services/core/java/com/android/server/power/ScreenTimeoutOverridePolicy.java b/services/core/java/com/android/server/power/ScreenTimeoutOverridePolicy.java
index dcb3c39..8e08ce9 100644
--- a/services/core/java/com/android/server/power/ScreenTimeoutOverridePolicy.java
+++ b/services/core/java/com/android/server/power/ScreenTimeoutOverridePolicy.java
@@ -83,6 +83,11 @@
public static final int RELEASE_REASON_USER_ACTIVITY_ACCESSIBILITY = 7;
/**
+ * Release reason code: Release because wakelock dies.
+ */
+ public static final int RELEASE_REASON_WAKE_LOCK_DEATH = 8;
+
+ /**
* @hide
*/
@IntDef(prefix = { "RELEASE_REASON_" }, value = {
@@ -93,7 +98,8 @@
RELEASE_REASON_USER_ACTIVITY_OTHER,
RELEASE_REASON_USER_ACTIVITY_BUTTON,
RELEASE_REASON_USER_ACTIVITY_TOUCH,
- RELEASE_REASON_USER_ACTIVITY_ACCESSIBILITY
+ RELEASE_REASON_USER_ACTIVITY_ACCESSIBILITY,
+ RELEASE_REASON_WAKE_LOCK_DEATH
})
@Retention(RetentionPolicy.SOURCE)
public @interface ReleaseReason{}
diff --git a/services/core/java/com/android/server/power/WakefulnessSessionObserver.java b/services/core/java/com/android/server/power/WakefulnessSessionObserver.java
index 3546565..c6b2602 100644
--- a/services/core/java/com/android/server/power/WakefulnessSessionObserver.java
+++ b/services/core/java/com/android/server/power/WakefulnessSessionObserver.java
@@ -31,6 +31,7 @@
import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_USER_ACTIVITY_BUTTON;
import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_USER_ACTIVITY_OTHER;
import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_USER_ACTIVITY_TOUCH;
+import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_WAKE_LOCK_DEATH;
import android.annotation.IntDef;
import android.app.ActivityManager;
@@ -574,10 +575,13 @@
case RELEASE_REASON_USER_ACTIVITY_ACCESSIBILITY:
outcome = OVERRIDE_OUTCOME_CANCEL_USER_INTERACTION;
break;
- case RELEASE_REASON_SCREEN_LOCK:
- case RELEASE_REASON_NON_INTERACTIVE:
+ case RELEASE_REASON_WAKE_LOCK_DEATH:
outcome = OVERRIDE_OUTCOME_CANCEL_CLIENT_DISCONNECT;
break;
+ case RELEASE_REASON_NON_INTERACTIVE:
+ case RELEASE_REASON_SCREEN_LOCK:
+ outcome = OVERRIDE_OUTCOME_CANCEL_OTHER;
+ break;
default:
outcome = OVERRIDE_OUTCOME_UNKNOWN;
}
diff --git a/services/core/java/com/android/server/power/stats/AggregatedPowerStats.java b/services/core/java/com/android/server/power/stats/AggregatedPowerStats.java
index e27f3b2..7496d2d 100644
--- a/services/core/java/com/android/server/power/stats/AggregatedPowerStats.java
+++ b/services/core/java/com/android/server/power/stats/AggregatedPowerStats.java
@@ -27,6 +27,7 @@
import android.util.IndentingPrintWriter;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import android.util.TimeUtils;
import com.android.internal.os.PowerStats;
@@ -73,14 +74,21 @@
private long mDurationMs;
AggregatedPowerStats(@NonNull AggregatedPowerStatsConfig aggregatedPowerStatsConfig) {
+ this(aggregatedPowerStatsConfig, new SparseBooleanArray());
+ }
+
+ AggregatedPowerStats(@NonNull AggregatedPowerStatsConfig aggregatedPowerStatsConfig,
+ @NonNull SparseBooleanArray enabledComponents) {
mConfig = aggregatedPowerStatsConfig;
List<PowerComponent> configs =
aggregatedPowerStatsConfig.getPowerComponentsAggregatedStatsConfigs();
mPowerComponentStats = new SparseArray<>(configs.size());
for (int i = 0; i < configs.size(); i++) {
PowerComponent powerComponent = configs.get(i);
- mPowerComponentStats.put(powerComponent.getPowerComponentId(),
- new PowerComponentAggregatedPowerStats(this, powerComponent));
+ if (enabledComponents.get(powerComponent.getPowerComponentId(), true)) {
+ mPowerComponentStats.put(powerComponent.getPowerComponentId(),
+ new PowerComponentAggregatedPowerStats(this, powerComponent));
+ }
}
mGenericPowerComponent = createGenericPowerComponent();
mPowerComponentStats.put(BatteryConsumer.POWER_COMPONENT_ANY, mGenericPowerComponent);
diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
index 143b3ff..c878f14 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -16393,6 +16393,10 @@
* Callers will need to wait for the collection to complete on the handler thread.
*/
public void schedulePowerStatsSampleCollection() {
+ if (!mSystemReady) {
+ return;
+ }
+
mCpuPowerStatsCollector.forceSchedule();
mScreenPowerStatsCollector.forceSchedule();
mMobileRadioPowerStatsCollector.forceSchedule();
@@ -16400,6 +16404,7 @@
mBluetoothPowerStatsCollector.forceSchedule();
mCameraPowerStatsCollector.forceSchedule();
mGnssPowerStatsCollector.forceSchedule();
+ mCustomEnergyConsumerPowerStatsCollector.forceSchedule();
}
/**
diff --git a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
index b308f38..d51cfea 100644
--- a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
+++ b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
@@ -428,5 +428,6 @@
*/
public void setPowerStatsExporterEnabled(int powerComponentId, boolean enabled) {
mPowerStatsExporterEnabled.put(powerComponentId, enabled);
+ mPowerStatsExporter.setPowerComponentEnabled(powerComponentId, enabled);
}
}
diff --git a/services/core/java/com/android/server/power/stats/CustomEnergyConsumerPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/CustomEnergyConsumerPowerStatsCollector.java
index 0273ba6..4bfe442 100644
--- a/services/core/java/com/android/server/power/stats/CustomEnergyConsumerPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/CustomEnergyConsumerPowerStatsCollector.java
@@ -68,6 +68,16 @@
}
@Override
+ public boolean forceSchedule() {
+ ensureInitialized();
+ boolean success = false;
+ for (int i = 0; i < mCollectors.size(); i++) {
+ success |= mCollectors.get(i).forceSchedule();
+ }
+ return success;
+ }
+
+ @Override
public void collectAndDump(PrintWriter pw) {
ensureInitialized();
for (int i = 0; i < mCollectors.size(); i++) {
diff --git a/services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsCollector.java
index ce11fa0..79fbe8e 100644
--- a/services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsCollector.java
@@ -163,10 +163,7 @@
mLayout.setConsumedEnergy(mPowerStats.stats, 0, uJtoUc(energyDelta, averageVoltage));
- for (int i = mPowerStats.uidStats.size() - 1; i >= 0; i--) {
- mLayout.setUidConsumedEnergy(mPowerStats.uidStats.valueAt(i), 0, 0);
- }
-
+ mPowerStats.uidStats.clear();
if (energy != null) {
for (int i = energy.length - 1; i >= 0; i--) {
EnergyConsumerAttribution[] perUid = energy[i].attribution;
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java b/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java
index 86f515c..081e560 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java
@@ -16,7 +16,9 @@
package com.android.server.power.stats;
import android.annotation.NonNull;
+import android.os.BatteryConsumer;
import android.os.BatteryStats;
+import android.util.SparseBooleanArray;
import com.android.internal.os.BatteryStatsHistory;
import com.android.internal.os.BatteryStatsHistoryIterator;
@@ -32,6 +34,8 @@
private static final long UNINITIALIZED = -1;
private final AggregatedPowerStatsConfig mAggregatedPowerStatsConfig;
private final BatteryStatsHistory mHistory;
+ private final SparseBooleanArray mEnabledComponents =
+ new SparseBooleanArray(BatteryConsumer.POWER_COMPONENT_COUNT + 10);
private AggregatedPowerStats mStats;
private int mCurrentBatteryState = AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
private int mCurrentScreenState = AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
@@ -42,8 +46,13 @@
mHistory = history;
}
- AggregatedPowerStatsConfig getConfig() {
- return mAggregatedPowerStatsConfig;
+ void setPowerComponentEnabled(int powerComponentId, boolean enabled) {
+ synchronized (this) {
+ if (mStats != null) {
+ mStats = null;
+ }
+ mEnabledComponents.put(powerComponentId, enabled);
+ }
}
/**
@@ -62,7 +71,7 @@
Consumer<AggregatedPowerStats> consumer) {
synchronized (this) {
if (mStats == null) {
- mStats = new AggregatedPowerStats(mAggregatedPowerStatsConfig);
+ mStats = new AggregatedPowerStats(mAggregatedPowerStatsConfig, mEnabledComponents);
}
mStats.start(startTimeMs);
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsExporter.java b/services/core/java/com/android/server/power/stats/PowerStatsExporter.java
index 5f41090..281faf1 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsExporter.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsExporter.java
@@ -216,6 +216,8 @@
PowerStatsLayout layout) {
AggregatedPowerStatsConfig.PowerComponent powerComponent = powerComponentStats.getConfig();
int powerComponentId = powerComponent.getPowerComponentId();
+ boolean isCustomComponent =
+ powerComponentId >= BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
PowerStats.Descriptor descriptor = powerComponentStats.getPowerStatsDescriptor();
long[] uidStats = new long[descriptor.uidStatsArrayLength];
@@ -223,7 +225,7 @@
boolean breakDownByProcState = batteryUsageStatsBuilder.isProcessStateDataNeeded()
&& powerComponent
.getUidStateConfig()[AggregatedPowerStatsConfig.STATE_PROCESS_STATE].isTracked()
- && powerComponentId < BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
+ && !isCustomComponent;
ArrayList<Integer> uids = new ArrayList<>();
powerComponentStats.collectUids(uids);
@@ -237,7 +239,7 @@
}
for (int powerState = 0; powerState < BatteryConsumer.POWER_STATE_COUNT; powerState++) {
- if (batteryUsageStatsBuilder.isPowerStateDataNeeded()) {
+ if (batteryUsageStatsBuilder.isPowerStateDataNeeded() && !isCustomComponent) {
if (powerState == BatteryConsumer.POWER_STATE_UNSPECIFIED) {
continue;
}
@@ -374,4 +376,8 @@
}
return true;
}
+
+ void setPowerComponentEnabled(int powerComponentId, boolean enabled) {
+ mPowerStatsAggregator.setPowerComponentEnabled(powerComponentId, enabled);
+ }
}
diff --git a/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java b/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java
index 52ef87c..06a2565 100644
--- a/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java
+++ b/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java
@@ -130,6 +130,7 @@
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.KeepForWeakReference;
import com.android.internal.camera.flags.Flags;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.os.BackgroundThread;
@@ -1944,8 +1945,12 @@
}
private class CallStateHelper {
- private OutgoingEmergencyStateCallback mEmergencyStateCallback;
- private CallStateCallback mCallStateCallback;
+ // TelephonyCallback instances are only weakly referenced when registered, so we need
+ // to ensure these fields are kept during optimization to preserve lifecycle semantics.
+ @KeepForWeakReference
+ private final OutgoingEmergencyStateCallback mEmergencyStateCallback;
+ @KeepForWeakReference
+ private final CallStateCallback mCallStateCallback;
private boolean mIsInEmergencyCall;
private boolean mMicUnmutedForEmergencyCall;
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index c21f783..331a594 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -1301,7 +1301,7 @@
final NetworkStats stats = getUidNetworkStatsSnapshotForTemplateLocked(
new NetworkTemplate.Builder(MATCH_PROXY).build(), /*includeTags=*/false);
if (stats != null) {
- ret.add(new NetworkStatsExt(sliceNetworkStatsByUidTagAndMetered(stats),
+ ret.add(new NetworkStatsExt(sliceNetworkStatsByUidAndFgbg(stats),
new int[]{TRANSPORT_BLUETOOTH},
/*slicedByFgbg=*/true, /*slicedByTag=*/false,
/*slicedByMetered=*/false, TelephonyManager.NETWORK_TYPE_UNKNOWN,
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index e4f60ec..a4a29a0 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -54,15 +54,13 @@
* Used by InputMethodManagerService to notify the IME status.
*
* @param displayId The display to which the IME is bound to.
- * @param token The IME token.
* @param vis Bit flags about the IME visibility.
* (e.g. {@link android.inputmethodservice.InputMethodService#IME_ACTIVE})
* @param backDisposition Bit flags about the IME back disposition.
* (e.g. {@link android.inputmethodservice.InputMethodService#BACK_DISPOSITION_DEFAULT})
* @param showImeSwitcher {@code true} when the IME switcher button should be shown.
*/
- void setImeWindowStatus(int displayId, IBinder token, int vis,
- int backDisposition, boolean showImeSwitcher);
+ void setImeWindowStatus(int displayId, int vis, int backDisposition, boolean showImeSwitcher);
/**
* See {@link android.app.StatusBarManager#setIcon(String, int, int, String)}.
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index e9423ce..c3601b3c 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -534,9 +534,9 @@
}
@Override
- public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
+ public void setImeWindowStatus(int displayId, int vis, int backDisposition,
boolean showImeSwitcher) {
- StatusBarManagerService.this.setImeWindowStatus(displayId, token, vis, backDisposition,
+ StatusBarManagerService.this.setImeWindowStatus(displayId, vis, backDisposition,
showImeSwitcher);
}
@@ -1351,25 +1351,24 @@
}
@Override
- public void setImeWindowStatus(int displayId, final IBinder token, final int vis,
- final int backDisposition, final boolean showImeSwitcher) {
+ public void setImeWindowStatus(int displayId, final int vis, final int backDisposition,
+ final boolean showImeSwitcher) {
enforceStatusBar();
if (SPEW) {
- Slog.d(TAG, "swetImeWindowStatus vis=" + vis + " backDisposition=" + backDisposition);
+ Slog.d(TAG, "setImeWindowStatus vis=" + vis + " backDisposition=" + backDisposition);
}
synchronized(mLock) {
// In case of IME change, we need to call up setImeWindowStatus() regardless of
// mImeWindowVis because mImeWindowVis may not have been set to false when the
// previous IME was destroyed.
- getUiState(displayId).setImeWindowState(vis, backDisposition, showImeSwitcher, token);
+ getUiState(displayId).setImeWindowState(vis, backDisposition, showImeSwitcher);
mHandler.post(() -> {
if (mBar == null) return;
try {
- mBar.setImeWindowStatus(
- displayId, token, vis, backDisposition, showImeSwitcher);
+ mBar.setImeWindowStatus(displayId, vis, backDisposition, showImeSwitcher);
} catch (RemoteException ex) { }
});
}
@@ -1422,7 +1421,6 @@
private int mImeWindowVis = 0;
private int mImeBackDisposition = 0;
private boolean mShowImeSwitcher = false;
- private IBinder mImeToken = null;
private LetterboxDetails[] mLetterboxDetails = new LetterboxDetails[0];
private void setBarAttributes(@Appearance int appearance,
@@ -1465,11 +1463,10 @@
}
private void setImeWindowState(final int vis, final int backDisposition,
- final boolean showImeSwitcher, final IBinder token) {
+ final boolean showImeSwitcher) {
mImeWindowVis = vis;
mImeBackDisposition = backDisposition;
mShowImeSwitcher = showImeSwitcher;
- mImeToken = token;
}
}
@@ -1563,7 +1560,7 @@
return new RegisterStatusBarResult(icons, gatherDisableActionsLocked(mCurrentUserId, 1),
state.mAppearance, state.mAppearanceRegions, state.mImeWindowVis,
state.mImeBackDisposition, state.mShowImeSwitcher,
- gatherDisableActionsLocked(mCurrentUserId, 2), state.mImeToken,
+ gatherDisableActionsLocked(mCurrentUserId, 2),
state.mNavbarColorManagedByIme, state.mBehavior, state.mRequestedVisibleTypes,
state.mPackageName, state.mTransientBarTypes, state.mLetterboxDetails);
}
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 023dd79..0c10551 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -68,7 +68,6 @@
import android.app.ActivityTaskManager;
import android.app.FullscreenRequestHandler;
import android.app.IActivityClientController;
-import android.app.ICompatCameraControlCallback;
import android.app.IRequestFinishCallback;
import android.app.PictureInPictureParams;
import android.app.PictureInPictureUiState;
@@ -1008,22 +1007,6 @@
Binder.restoreCallingIdentity(origId);
}
- @Override
- public void requestCompatCameraControl(IBinder token, boolean showControl,
- boolean transformationApplied, ICompatCameraControlCallback callback) {
- final long origId = Binder.clearCallingIdentity();
- try {
- synchronized (mGlobalLock) {
- final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
- if (r != null) {
- r.updateCameraCompatState(showControl, transformationApplied, callback);
- }
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
-
/**
* Initialize the {@link #mSetPipAspectRatioQuotaTracker} if applicable, which should happen
* out of {@link #mGlobalLock} to avoid deadlock (AM lock is used in QuotaTrack ctor).
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index b3208bf..fb2bf39 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -4,10 +4,6 @@
import static android.app.ActivityManager.START_SUCCESS;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.ActivityManager.processStateAmToProto;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
import static android.app.WaitResult.INVALID_DELAY;
import static android.app.WaitResult.LAUNCH_STATE_COLD;
import static android.app.WaitResult.LAUNCH_STATE_HOT;
@@ -69,11 +65,6 @@
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__NOT_VISIBLE;
import static com.android.internal.util.FrameworkStatsLog.APP_START_OCCURRED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL;
import static com.android.internal.util.FrameworkStatsLog.APP_START_OCCURRED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_STOPPED;
-import static com.android.internal.util.FrameworkStatsLog.CAMERA_COMPAT_CONTROL_EVENT_REPORTED__EVENT__APPEARED_APPLY_TREATMENT;
-import static com.android.internal.util.FrameworkStatsLog.CAMERA_COMPAT_CONTROL_EVENT_REPORTED__EVENT__APPEARED_REVERT_TREATMENT;
-import static com.android.internal.util.FrameworkStatsLog.CAMERA_COMPAT_CONTROL_EVENT_REPORTED__EVENT__CLICKED_APPLY_TREATMENT;
-import static com.android.internal.util.FrameworkStatsLog.CAMERA_COMPAT_CONTROL_EVENT_REPORTED__EVENT__CLICKED_DISMISS;
-import static com.android.internal.util.FrameworkStatsLog.CAMERA_COMPAT_CONTROL_EVENT_REPORTED__EVENT__CLICKED_REVERT_TREATMENT;
import static com.android.server.am.MemoryStatUtil.MemoryStat;
import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
import static com.android.server.am.ProcessList.INVALID_ADJ;
@@ -89,7 +80,6 @@
import android.app.ActivityOptions;
import android.app.ActivityOptions.SourceInfo;
import android.app.ApplicationStartInfo;
-import android.app.CameraCompatTaskInfo.CameraCompatControlState;
import android.app.WaitResult;
import android.app.WindowConfiguration.WindowingMode;
import android.content.ComponentName;
@@ -1622,7 +1612,8 @@
int positionToLog = APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__NOT_LETTERBOXED_POSITION;
if (isAppCompateStateChangedToLetterboxed(state)) {
- positionToLog = activity.mLetterboxUiController.getLetterboxPositionForLogging();
+ positionToLog = activity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .getLetterboxPositionForLogging();
}
FrameworkStatsLog.write(FrameworkStatsLog.APP_COMPAT_STATE_CHANGED,
packageUid, state, positionToLog);
@@ -1662,71 +1653,6 @@
}
}
- /**
- * Logs the Camera Compat Control appeared event that corresponds to the given {@code state}
- * with the given {@code packageUid}.
- */
- void logCameraCompatControlAppearedEventReported(@CameraCompatControlState int state,
- int packageUid) {
- switch (state) {
- case CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED:
- logCameraCompatControlEventReported(
- CAMERA_COMPAT_CONTROL_EVENT_REPORTED__EVENT__APPEARED_APPLY_TREATMENT,
- packageUid);
- break;
- case CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED:
- logCameraCompatControlEventReported(
- CAMERA_COMPAT_CONTROL_EVENT_REPORTED__EVENT__APPEARED_REVERT_TREATMENT,
- packageUid);
- break;
- case CAMERA_COMPAT_CONTROL_HIDDEN:
- // Nothing to log.
- break;
- default:
- Slog.w(TAG, "Unexpected state in logCameraCompatControlAppearedEventReported: "
- + state);
- break;
- }
- }
-
- /**
- * Logs the Camera Compat Control clicked event that corresponds to the given {@code state}
- * with the given {@code packageUid}.
- */
- void logCameraCompatControlClickedEventReported(@CameraCompatControlState int state,
- int packageUid) {
- switch (state) {
- case CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED:
- logCameraCompatControlEventReported(
- CAMERA_COMPAT_CONTROL_EVENT_REPORTED__EVENT__CLICKED_APPLY_TREATMENT,
- packageUid);
- break;
- case CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED:
- logCameraCompatControlEventReported(
- CAMERA_COMPAT_CONTROL_EVENT_REPORTED__EVENT__CLICKED_REVERT_TREATMENT,
- packageUid);
- break;
- case CAMERA_COMPAT_CONTROL_DISMISSED:
- logCameraCompatControlEventReported(
- CAMERA_COMPAT_CONTROL_EVENT_REPORTED__EVENT__CLICKED_DISMISS,
- packageUid);
- break;
- default:
- Slog.w(TAG, "Unexpected state in logCameraCompatControlAppearedEventReported: "
- + state);
- break;
- }
- }
-
- private void logCameraCompatControlEventReported(int event, int packageUid) {
- FrameworkStatsLog.write(FrameworkStatsLog.CAMERA_COMPAT_CONTROL_EVENT_REPORTED, packageUid,
- event);
- if (DEBUG_METRICS) {
- Slog.i(TAG, String.format("CAMERA_COMPAT_CONTROL_EVENT_REPORTED(%s, %s)", packageUid,
- event));
- }
- }
-
private ArtManagerInternal getArtManagerInternal() {
if (mArtManagerInternal == null) {
// Note that this may be null.
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 7d70ea1..7210098 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -33,12 +33,7 @@
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_FREEFORM_NONE;
-import static android.app.CameraCompatTaskInfo.cameraCompatControlStateToString;
import static android.app.WaitResult.INVALID_DELAY;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
@@ -271,8 +266,6 @@
import android.app.Activity;
import android.app.ActivityManager.TaskDescription;
import android.app.ActivityOptions;
-import android.app.CameraCompatTaskInfo.CameraCompatControlState;
-import android.app.ICompatCameraControlCallback;
import android.app.IScreenCaptureObserver;
import android.app.PendingIntent;
import android.app.PictureInPictureParams;
@@ -371,6 +364,7 @@
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.KeepForWeakReference;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity;
import com.android.internal.content.ReferrerIntent;
@@ -824,19 +818,6 @@
// and therefore #isLetterboxedForFixedOrientationAndAspectRatio returns false.
private boolean mIsEligibleForFixedOrientationLetterbox;
- // State of the Camera app compat control which is used to correct stretched viewfinder
- // in apps that don't handle all possible configurations and changes between them correctly.
- @CameraCompatControlState
- private int mCameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN;
-
- // The callback that allows to ask the calling View to apply the treatment for stretched
- // issues affecting camera viewfinders when the user clicks on the camera compat control.
- @Nullable
- private ICompatCameraControlCallback mCompatCameraControlCallback;
-
- private final boolean mCameraCompatControlEnabled;
- private boolean mCameraCompatControlClickedByUser;
-
// activity is not displayed?
// TODO: rename to mNoDisplay
@VisibleForTesting
@@ -941,6 +922,8 @@
private RemoteCallbackList<IScreenCaptureObserver> mCaptureCallbacks;
+ // Ensure the field is kept during optimization to preserve downstream weak refs.
+ @KeepForWeakReference
private final ColorDisplayService.ColorTransformController mColorTransformController =
(matrix, translation) -> mWmService.mH.post(() -> {
synchronized (mWmService.mGlobalLock) {
@@ -1342,10 +1325,6 @@
}
mLetterboxUiController.dump(pw, prefix);
-
- pw.println(prefix + "mCameraCompatControlState="
- + cameraCompatControlStateToString(mCameraCompatControlState));
- pw.println(prefix + "mCameraCompatControlEnabled=" + mCameraCompatControlEnabled);
}
static boolean dumpActivity(FileDescriptor fd, PrintWriter pw, int index, ActivityRecord r,
@@ -1884,100 +1863,6 @@
mLetterboxUiController.getLetterboxInnerBounds(outBounds);
}
- void updateCameraCompatState(boolean showControl, boolean transformationApplied,
- ICompatCameraControlCallback callback) {
- if (!isCameraCompatControlEnabled()) {
- // Feature is disabled by config_isCameraCompatControlForStretchedIssuesEnabled.
- return;
- }
- if (mCameraCompatControlClickedByUser && (showControl
- || mCameraCompatControlState == CAMERA_COMPAT_CONTROL_DISMISSED)) {
- // The user already applied treatment on this activity or dismissed control.
- // Respecting their choice.
- return;
- }
- mCompatCameraControlCallback = callback;
- int newCameraCompatControlState = !showControl
- ? CAMERA_COMPAT_CONTROL_HIDDEN
- : transformationApplied
- ? CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED
- : CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
- boolean changed = setCameraCompatControlState(newCameraCompatControlState);
- if (!changed) {
- return;
- }
- mTaskSupervisor.getActivityMetricsLogger().logCameraCompatControlAppearedEventReported(
- newCameraCompatControlState, info.applicationInfo.uid);
- if (newCameraCompatControlState == CAMERA_COMPAT_CONTROL_HIDDEN) {
- mCameraCompatControlClickedByUser = false;
- mCompatCameraControlCallback = null;
- }
- // Trigger TaskInfoChanged to update the camera compat UI.
- getTask().dispatchTaskInfoChangedIfNeeded(true /* force */);
- // TaskOrganizerController#onTaskInfoChanged adds pending task events to the queue waiting
- // for the surface placement to be ready. So need to trigger surface placement to dispatch
- // events to avoid stale state for the camera compat control.
- getDisplayContent().setLayoutNeeded();
- mWmService.mWindowPlacerLocked.performSurfacePlacement();
- }
-
- void updateCameraCompatStateFromUser(@CameraCompatControlState int state) {
- if (!isCameraCompatControlEnabled()) {
- // Feature is disabled by config_isCameraCompatControlForStretchedIssuesEnabled.
- return;
- }
- if (state == CAMERA_COMPAT_CONTROL_HIDDEN) {
- Slog.w(TAG, "Unexpected hidden state in updateCameraCompatState");
- return;
- }
- boolean changed = setCameraCompatControlState(state);
- mCameraCompatControlClickedByUser = true;
- if (!changed) {
- return;
- }
- mTaskSupervisor.getActivityMetricsLogger().logCameraCompatControlClickedEventReported(
- state, info.applicationInfo.uid);
- if (state == CAMERA_COMPAT_CONTROL_DISMISSED) {
- mCompatCameraControlCallback = null;
- return;
- }
- if (mCompatCameraControlCallback == null) {
- Slog.w(TAG, "Callback for a camera compat control is null");
- return;
- }
- try {
- if (state == CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED) {
- mCompatCameraControlCallback.applyCameraCompatTreatment();
- } else {
- mCompatCameraControlCallback.revertCameraCompatTreatment();
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to apply or revert camera compat treatment", e);
- }
- }
-
- private boolean setCameraCompatControlState(@CameraCompatControlState int state) {
- if (!isCameraCompatControlEnabled()) {
- // Feature is disabled by config_isCameraCompatControlForStretchedIssuesEnabled.
- return false;
- }
- if (mCameraCompatControlState != state) {
- mCameraCompatControlState = state;
- return true;
- }
- return false;
- }
-
- @CameraCompatControlState
- int getCameraCompatControlState() {
- return mCameraCompatControlState;
- }
-
- @VisibleForTesting
- boolean isCameraCompatControlEnabled() {
- return mCameraCompatControlEnabled;
- }
-
/**
* @return {@code true} if bar shown within a given rectangle is allowed to be fully transparent
* when the current activity is displayed.
@@ -2103,10 +1988,8 @@
// Don't move below setOrientation(info.screenOrientation) since it triggers
// getOverrideOrientation that requires having mLetterboxUiController
// initialised.
- mLetterboxUiController = new LetterboxUiController(mWmService, this);
mAppCompatController = new AppCompatController(mWmService, this);
- mCameraCompatControlEnabled = mWmService.mContext.getResources()
- .getBoolean(R.bool.config_isCameraCompatControlForStretchedIssuesEnabled);
+ mLetterboxUiController = new LetterboxUiController(mWmService, this);
mResolveConfigHint = new TaskFragment.ConfigOverrideHint();
if (mWmService.mFlags.mInsetsDecoupledConfiguration) {
// When the stable configuration is the default behavior, override for the legacy apps
@@ -8750,8 +8633,8 @@
/**
* Adjusts position of resolved bounds if they don't fill the parent using gravity
* requested in the config or via an ADB command. For more context see {@link
- * LetterboxUiController#getHorizontalPositionMultiplier(Configuration)} and
- * {@link LetterboxUiController#getVerticalPositionMultiplier(Configuration)}
+ * AppCompatReachabilityOverrides#getHorizontalPositionMultiplier(Configuration)} and
+ * {@link AppCompatReachabilityOverrides#getVerticalPositionMultiplier(Configuration)}
* <p>
* Note that this is the final step that can change the resolved bounds. After this method
* is called, the position of the bounds will be moved to app space as sandboxing if the
@@ -8780,11 +8663,13 @@
} else {
navBarInsets = Insets.NONE;
}
+ final AppCompatReachabilityOverrides reachabilityOverrides =
+ mAppCompatController.getAppCompatReachabilityOverrides();
// Horizontal position
int offsetX = 0;
if (parentBounds.width() != screenResolvedBoundsWidth) {
if (screenResolvedBoundsWidth <= parentAppBoundsWidth) {
- float positionMultiplier = mLetterboxUiController.getHorizontalPositionMultiplier(
+ float positionMultiplier = reachabilityOverrides.getHorizontalPositionMultiplier(
newParentConfiguration);
// If in immersive mode, always align to right and overlap right insets (task bar)
// as they are transient and hidden. This removes awkward right spacing.
@@ -8805,7 +8690,7 @@
int offsetY = 0;
if (parentBoundsHeight != screenResolvedBoundsHeight) {
if (screenResolvedBoundsHeight <= parentAppBoundsHeight) {
- float positionMultiplier = mLetterboxUiController.getVerticalPositionMultiplier(
+ float positionMultiplier = reachabilityOverrides.getVerticalPositionMultiplier(
newParentConfiguration);
// If in immersive mode, always align to bottom and overlap bottom insets (nav bar,
// task bar) as they are transient and hidden. This removes awkward bottom spacing.
@@ -10803,6 +10688,9 @@
return true;
}
}
+ if (mAtmService.mBackNavigationController.isStartingSurfaceShown(this)) {
+ return true;
+ }
if (!super.isSyncFinished(group)) return false;
if (mDisplayContent != null && mDisplayContent.mUnknownAppVisibilityController
.isVisibilityUnknown(this)) {
diff --git a/services/core/java/com/android/server/wm/ActivitySnapshotController.java b/services/core/java/com/android/server/wm/ActivitySnapshotController.java
index aa63393..24ed1bb 100644
--- a/services/core/java/com/android/server/wm/ActivitySnapshotController.java
+++ b/services/core/java/com/android/server/wm/ActivitySnapshotController.java
@@ -23,7 +23,6 @@
import android.app.ActivityManager;
import android.graphics.Rect;
import android.os.Environment;
-import android.os.SystemProperties;
import android.os.Trace;
import android.util.ArraySet;
import android.util.IntArray;
@@ -33,7 +32,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wm.BaseAppSnapshotPersister.PersistInfoProvider;
-import com.android.window.flags.Flags;
import java.io.File;
import java.io.PrintWriter;
@@ -109,7 +107,6 @@
!service.mContext
.getResources()
.getBoolean(com.android.internal.R.bool.config_disableTaskSnapshots)
- && isSnapshotEnabled()
&& !ActivityManager.isLowRamDeviceStatic(); // Don't support Android Go
setSnapshotEnabled(snapshotEnabled);
}
@@ -121,12 +118,6 @@
return Math.max(Math.min(config, 1f), 0.1f);
}
- // TODO remove when enabled
- static boolean isSnapshotEnabled() {
- return SystemProperties.getInt("persist.wm.debug.activity_screenshot", 0) != 0
- || Flags.activitySnapshotByDefault();
- }
-
static PersistInfoProvider createPersistInfoProvider(
WindowManagerService service, BaseAppSnapshotPersister.DirectoryResolver resolver) {
// Don't persist reduced file, instead we only persist the "HighRes" bitmap which has
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index c89f3a3..2f6e7de 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -28,6 +28,8 @@
import static android.app.ActivityManager.START_SUCCESS;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
+import static android.app.PendingIntent.FLAG_ONE_SHOT;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
@@ -146,6 +148,7 @@
import java.lang.annotation.RetentionPolicy;
import java.text.DateFormat;
import java.util.Date;
+import java.util.function.Supplier;
/**
* Controller for interpreting how and then launching an activity.
@@ -2079,9 +2082,23 @@
? targetTask.getWindowingMode() : displayContent.getWindowingMode();
final int launchingFromDisplayId =
mSourceRecord != null ? mSourceRecord.getDisplayId() : DEFAULT_DISPLAY;
+ final boolean isResultExpected = r.resultTo != null;
+ Supplier<IntentSender> intentSender = null;
+ if (android.companion.virtualdevice.flags.Flags.activityControlApi()) {
+ intentSender = () -> {
+ IIntentSender target = mService.getIntentSenderLocked(
+ ActivityManager.INTENT_SENDER_ACTIVITY, mRequest.callingPackage,
+ mRequest.callingFeatureId, mCallingUid, r.mUserId,
+ /* token= */ null, /* resultCode= */ null, /* requestCode= */ 0,
+ new Intent[]{ mIntent }, new String[]{ r.resolvedType },
+ FLAG_CANCEL_CURRENT | FLAG_ONE_SHOT,
+ mOptions == null ? null : mOptions.toBundle());
+ return new IntentSender(target);
+ };
+ }
if (!displayContent.mDwpcHelper
.canActivityBeLaunched(r.info, r.intent, targetWindowingMode,
- launchingFromDisplayId, newTask)) {
+ launchingFromDisplayId, newTask, isResultExpected, intentSender)) {
Slog.w(TAG, "Abort to launch " + r.info.getComponentName()
+ " on display area " + mPreferredTaskDisplayArea);
return START_ABORTED;
@@ -2540,9 +2557,7 @@
if (!mOptions.canTaskOverlayResume()) {
final Task task = mRootWindowContainer.anyTaskForId(
mOptions.getLaunchTaskId());
- final ActivityRecord top = task != null
- ? task.getTopNonFinishingActivity() : null;
- if (top != null && !top.isState(RESUMED)) {
+ if (task != null && !task.canBeResumed(r)) {
// The caller specifies that we'd like to be avoided to be moved to the
// front, so be it!
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 1c14c5d..9f3bbd1 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -7175,25 +7175,6 @@
}
/**
- * Checks if the given user is a visible background user, which is a full, background user
- * assigned to secondary displays on the devices that have
- * {@link UserManager#isVisibleBackgroundUsersEnabled()
- * config_multiuserVisibleBackgroundUsers enabled} (for example, passenger users on
- * automotive builds, using the display associated with their seats).
- *
- * @see UserManager#isUserVisible()
- */
- private boolean isVisibleBackgroundUser(int userId) {
- if (!UserManager.isVisibleBackgroundUsersEnabled()) {
- return false;
- }
- boolean isForeground = getCurrentUserId() == userId;
- boolean isProfile = getUserManager().isProfile(userId);
- boolean isVisible = mWindowManager.mUmInternal.isUserVisible(userId);
- return isVisible && !isForeground && !isProfile;
- }
-
- /**
* In a car environment, {@link ActivityTaskManagerService#mShowDialogs} is always set to
* {@code false} from {@link ActivityTaskManagerService#updateShouldShowDialogsLocked}
* because its UI mode is {@link Configuration#UI_MODE_TYPE_CAR}. Thus, error dialogs are
@@ -7208,7 +7189,7 @@
* @see ActivityTaskManagerService#updateShouldShowDialogsLocked
*/
private boolean shouldShowDialogsForVisibleBackgroundUserLocked(int userId) {
- if (!isVisibleBackgroundUser(userId)) {
+ if (!mWindowManager.mUmInternal.isVisibleBackgroundFullUser(userId)) {
return false;
}
final int displayId = mWindowManager.mUmInternal.getMainDisplayAssignedToUser(userId);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index afdbc0a..509a060 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -2901,6 +2901,8 @@
ActivityRecord fillAndReturnTop(Task task, TaskInfo info) {
info.numActivities = 0;
info.baseActivity = null;
+ info.capturedLink = null;
+ info.capturedLinkTimestamp = 0;
mInfo = info;
task.forAllActivities(this);
final ActivityRecord top = mTopRunning;
diff --git a/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java b/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java
index 25cb134..d2f3d1d 100644
--- a/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java
+++ b/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java
@@ -50,8 +50,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wm.utils.OptPropFactory;
-import java.util.function.Function;
-
/**
* Encapsulates app compat configurations and overrides related to aspect ratio.
*/
@@ -76,20 +74,20 @@
@NonNull
private final OptPropFactory.OptProp mAllowOrientationOverrideOptProp;
@NonNull
- private final Function<Boolean, Boolean> mIsDisplayFullScreenAndInPostureProvider;
+ private final AppCompatDeviceStateQuery mAppCompatDeviceStateQuery;
@NonNull
- private final Function<Configuration, Float> mGetHorizontalPositionMultiplierProvider;
+ private final AppCompatReachabilityOverrides mAppCompatReachabilityOverrides;
AppCompatAspectRatioOverrides(@NonNull ActivityRecord activityRecord,
@NonNull AppCompatConfiguration appCompatConfiguration,
@NonNull OptPropFactory optPropBuilder,
- @NonNull Function<Boolean, Boolean> isDisplayFullScreenAndInPostureProvider,
- @NonNull Function<Configuration, Float> getHorizontalPositionMultiplierProvider) {
+ @NonNull AppCompatDeviceStateQuery appCompatDeviceStateQuery,
+ @NonNull AppCompatReachabilityOverrides appCompatReachabilityOverrides) {
mActivityRecord = activityRecord;
mAppCompatConfiguration = appCompatConfiguration;
+ mAppCompatDeviceStateQuery = appCompatDeviceStateQuery;
mUserAspectRatioState = new UserAspectRatioState();
- mIsDisplayFullScreenAndInPostureProvider = isDisplayFullScreenAndInPostureProvider;
- mGetHorizontalPositionMultiplierProvider = getHorizontalPositionMultiplierProvider;
+ mAppCompatReachabilityOverrides = appCompatReachabilityOverrides;
mAllowMinAspectRatioOverrideOptProp = optPropBuilder.create(
PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE);
mAllowUserAspectRatioOverrideOptProp = optPropBuilder.create(
@@ -245,12 +243,13 @@
}
private boolean shouldUseSplitScreenAspectRatio(@NonNull Configuration parentConfiguration) {
- final boolean isBookMode = mIsDisplayFullScreenAndInPostureProvider
- .apply(/* isTabletop */false);
- final boolean isNotCenteredHorizontally = mGetHorizontalPositionMultiplierProvider.apply(
- parentConfiguration) != LETTERBOX_POSITION_MULTIPLIER_CENTER;
- final boolean isTabletopMode = mIsDisplayFullScreenAndInPostureProvider
- .apply(/* isTabletop */ true);
+ final boolean isBookMode = mAppCompatDeviceStateQuery
+ .isDisplayFullScreenAndInPosture(/* isTabletop */false);
+ final boolean isNotCenteredHorizontally =
+ mAppCompatReachabilityOverrides.getHorizontalPositionMultiplier(parentConfiguration)
+ != LETTERBOX_POSITION_MULTIPLIER_CENTER;
+ final boolean isTabletopMode = mAppCompatDeviceStateQuery
+ .isDisplayFullScreenAndInPosture(/* isTabletop */ true);
final boolean isLandscape = isFixedOrientationLandscape(
mActivityRecord.getOverrideOrientation());
final AppCompatCameraOverrides cameraOverrides =
diff --git a/services/core/java/com/android/server/wm/AppCompatController.java b/services/core/java/com/android/server/wm/AppCompatController.java
index 54223b6..d38edfc 100644
--- a/services/core/java/com/android/server/wm/AppCompatController.java
+++ b/services/core/java/com/android/server/wm/AppCompatController.java
@@ -35,7 +35,11 @@
@NonNull
private final AppCompatAspectRatioPolicy mAppCompatAspectRatioPolicy;
@NonNull
+ private final AppCompatReachabilityPolicy mAppCompatReachabilityPolicy;
+ @NonNull
private final AppCompatOverrides mAppCompatOverrides;
+ @NonNull
+ private final AppCompatDeviceStateQuery mAppCompatDeviceStateQuery;
AppCompatController(@NonNull WindowManagerService wmService,
@NonNull ActivityRecord activityRecord) {
@@ -43,13 +47,16 @@
final PackageManager packageManager = wmService.mContext.getPackageManager();
final OptPropFactory optPropBuilder = new OptPropFactory(packageManager,
activityRecord.packageName);
+ mAppCompatDeviceStateQuery = new AppCompatDeviceStateQuery(activityRecord);
mTransparentPolicy = new TransparentPolicy(activityRecord,
wmService.mAppCompatConfiguration);
mAppCompatOverrides = new AppCompatOverrides(activityRecord,
- wmService.mAppCompatConfiguration, optPropBuilder);
+ wmService.mAppCompatConfiguration, optPropBuilder, mAppCompatDeviceStateQuery);
mOrientationPolicy = new AppCompatOrientationPolicy(activityRecord, mAppCompatOverrides);
mAppCompatAspectRatioPolicy = new AppCompatAspectRatioPolicy(activityRecord,
mTransparentPolicy, mAppCompatOverrides);
+ mAppCompatReachabilityPolicy = new AppCompatReachabilityPolicy(mActivityRecord,
+ wmService.mAppCompatConfiguration);
}
@NonNull
@@ -101,7 +108,23 @@
}
@NonNull
+ AppCompatReachabilityPolicy getAppCompatReachabilityPolicy() {
+ return mAppCompatReachabilityPolicy;
+ }
+
+ @NonNull
AppCompatFocusOverrides getAppCompatFocusOverrides() {
return mAppCompatOverrides.getAppCompatFocusOverrides();
}
+
+ @NonNull
+ AppCompatReachabilityOverrides getAppCompatReachabilityOverrides() {
+ return mAppCompatOverrides.getAppCompatReachabilityOverrides();
+ }
+
+ @NonNull
+ AppCompatDeviceStateQuery getAppCompatDeviceStateQuery() {
+ return mAppCompatDeviceStateQuery;
+ }
+
}
diff --git a/services/core/java/com/android/server/wm/AppCompatDeviceStateQuery.java b/services/core/java/com/android/server/wm/AppCompatDeviceStateQuery.java
new file mode 100644
index 0000000..3abea24
--- /dev/null
+++ b/services/core/java/com/android/server/wm/AppCompatDeviceStateQuery.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
+import android.annotation.NonNull;
+
+/**
+ * Provides information about the current state of the display in relation of
+ * fold/unfold and other positions.
+ */
+class AppCompatDeviceStateQuery {
+
+ @NonNull
+ final ActivityRecord mActivityRecord;
+
+ AppCompatDeviceStateQuery(@NonNull ActivityRecord activityRecord) {
+ mActivityRecord = activityRecord;
+ }
+
+ /**
+ * Check if we are in the given pose and in fullscreen mode.
+ *
+ * Note that we check the task rather than the parent as with ActivityEmbedding the parent
+ * might be a TaskFragment, and its windowing mode is always MULTI_WINDOW, even if the task is
+ * actually fullscreen. If display is still in transition e.g. unfolding, don't return true
+ * for HALF_FOLDED state or app will flicker.
+ */
+ boolean isDisplayFullScreenAndInPosture(boolean isTabletop) {
+ final Task task = mActivityRecord.getTask();
+ final DisplayContent dc = mActivityRecord.mDisplayContent;
+ return dc != null && task != null && !dc.inTransition()
+ && dc.getDisplayRotation().isDeviceInPosture(
+ DeviceStateController.DeviceState.HALF_FOLDED, isTabletop)
+ && task.getWindowingMode() == WINDOWING_MODE_FULLSCREEN;
+ }
+
+ /**
+ * Note that we check the task rather than the parent as with ActivityEmbedding the parent might
+ * be a TaskFragment, and its windowing mode is always MULTI_WINDOW, even if the task is
+ * actually fullscreen.
+ */
+ boolean isDisplayFullScreenAndSeparatingHinge() {
+ final Task task = mActivityRecord.getTask();
+ return mActivityRecord.mDisplayContent != null && task != null
+ && mActivityRecord.mDisplayContent.getDisplayRotation().isDisplaySeparatingHinge()
+ && task.getWindowingMode() == WINDOWING_MODE_FULLSCREEN;
+ }
+}
diff --git a/services/core/java/com/android/server/wm/AppCompatOverrides.java b/services/core/java/com/android/server/wm/AppCompatOverrides.java
index 4450011..80bbee3 100644
--- a/services/core/java/com/android/server/wm/AppCompatOverrides.java
+++ b/services/core/java/com/android/server/wm/AppCompatOverrides.java
@@ -35,19 +35,22 @@
private final AppCompatFocusOverrides mAppCompatFocusOverrides;
@NonNull
private final AppCompatResizeOverrides mAppCompatResizeOverrides;
+ @NonNull
+ private final AppCompatReachabilityOverrides mAppCompatReachabilityOverrides;
AppCompatOverrides(@NonNull ActivityRecord activityRecord,
@NonNull AppCompatConfiguration appCompatConfiguration,
- @NonNull OptPropFactory optPropBuilder) {
+ @NonNull OptPropFactory optPropBuilder,
+ @NonNull AppCompatDeviceStateQuery appCompatDeviceStateQuery) {
mAppCompatCameraOverrides = new AppCompatCameraOverrides(activityRecord,
appCompatConfiguration, optPropBuilder);
mAppCompatOrientationOverrides = new AppCompatOrientationOverrides(activityRecord,
appCompatConfiguration, optPropBuilder, mAppCompatCameraOverrides);
- // TODO(b/341903757) Remove BooleanSuppliers after fixing dependency with reachability.
+ mAppCompatReachabilityOverrides = new AppCompatReachabilityOverrides(activityRecord,
+ appCompatConfiguration, appCompatDeviceStateQuery);
mAppCompatAspectRatioOverrides = new AppCompatAspectRatioOverrides(activityRecord,
- appCompatConfiguration, optPropBuilder,
- activityRecord.mLetterboxUiController::isDisplayFullScreenAndInPosture,
- activityRecord.mLetterboxUiController::getHorizontalPositionMultiplier);
+ appCompatConfiguration, optPropBuilder, appCompatDeviceStateQuery,
+ mAppCompatReachabilityOverrides);
mAppCompatFocusOverrides = new AppCompatFocusOverrides(activityRecord,
appCompatConfiguration, optPropBuilder);
mAppCompatResizeOverrides = new AppCompatResizeOverrides(activityRecord, optPropBuilder);
@@ -77,4 +80,9 @@
AppCompatResizeOverrides getAppCompatResizeOverrides() {
return mAppCompatResizeOverrides;
}
+
+ @NonNull
+ AppCompatReachabilityOverrides getAppCompatReachabilityOverrides() {
+ return mAppCompatReachabilityOverrides;
+ }
}
diff --git a/services/core/java/com/android/server/wm/AppCompatReachabilityOverrides.java b/services/core/java/com/android/server/wm/AppCompatReachabilityOverrides.java
new file mode 100644
index 0000000..b9bdc32
--- /dev/null
+++ b/services/core/java/com/android/server/wm/AppCompatReachabilityOverrides.java
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
+import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__BOTTOM;
+import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__CENTER;
+import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__LEFT;
+import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__RIGHT;
+import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__TOP;
+import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__UNKNOWN_POSITION;
+import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER;
+import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT;
+import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT;
+import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM;
+import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER;
+import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP;
+
+import android.annotation.NonNull;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.window.flags.Flags;
+
+/**
+ * Encapsulate overrides and configurations about app compat reachability.
+ */
+class AppCompatReachabilityOverrides {
+
+ @NonNull
+ private final ActivityRecord mActivityRecord;
+ @NonNull
+ private final AppCompatConfiguration mAppCompatConfiguration;
+ @NonNull
+ private final AppCompatDeviceStateQuery mAppCompatDeviceStateQuery;
+ @NonNull
+ private final ReachabilityState mReachabilityState;
+
+ AppCompatReachabilityOverrides(@NonNull ActivityRecord activityRecord,
+ @NonNull AppCompatConfiguration appCompatConfiguration,
+ @NonNull AppCompatDeviceStateQuery appCompatDeviceStateQuery) {
+ mActivityRecord = activityRecord;
+ mAppCompatConfiguration = appCompatConfiguration;
+ mAppCompatDeviceStateQuery = appCompatDeviceStateQuery;
+ mReachabilityState = new ReachabilityState();
+ }
+
+ boolean isFromDoubleTap() {
+ return mReachabilityState.isFromDoubleTap();
+ }
+
+ boolean isDoubleTapEvent() {
+ return mReachabilityState.mIsDoubleTapEvent;
+ }
+
+ void setDoubleTapEvent() {
+ mReachabilityState.mIsDoubleTapEvent = true;
+ }
+
+ /**
+ * Provides the multiplier to use when calculating the position of a letterboxed app after
+ * an horizontal reachability event (double tap). The method takes the current state of the
+ * device (e.g. device in book mode) into account.
+ * </p>
+ * @param parentConfiguration The parent {@link Configuration}.
+ * @return The value to use for calculating the letterbox horizontal position.
+ */
+ float getHorizontalPositionMultiplier(@NonNull Configuration parentConfiguration) {
+ // Don't check resolved configuration because it may not be updated yet during
+ // configuration change.
+ boolean bookModeEnabled = isFullScreenAndBookModeEnabled();
+ return isHorizontalReachabilityEnabled(parentConfiguration)
+ // Using the last global dynamic position to avoid "jumps" when moving
+ // between apps or activities.
+ ? mAppCompatConfiguration.getHorizontalMultiplierForReachability(bookModeEnabled)
+ : mAppCompatConfiguration.getLetterboxHorizontalPositionMultiplier(bookModeEnabled);
+ }
+
+ /**
+ * Provides the multiplier to use when calculating the position of a letterboxed app after
+ * a vertical reachability event (double tap). The method takes the current state of the
+ * device (e.g. device posture) into account.
+ * </p>
+ * @param parentConfiguration The parent {@link Configuration}.
+ * @return The value to use for calculating the letterbox horizontal position.
+ */
+ float getVerticalPositionMultiplier(@NonNull Configuration parentConfiguration) {
+ // Don't check resolved configuration because it may not be updated yet during
+ // configuration change.
+ boolean tabletopMode = mAppCompatDeviceStateQuery
+ .isDisplayFullScreenAndInPosture(/* isTabletop */ true);
+ return isVerticalReachabilityEnabled(parentConfiguration)
+ // Using the last global dynamic position to avoid "jumps" when moving
+ // between apps or activities.
+ ? mAppCompatConfiguration.getVerticalMultiplierForReachability(tabletopMode)
+ : mAppCompatConfiguration.getLetterboxVerticalPositionMultiplier(tabletopMode);
+ }
+
+ @VisibleForTesting
+ boolean isHorizontalReachabilityEnabled() {
+ return isHorizontalReachabilityEnabled(mActivityRecord.getParent().getConfiguration());
+ }
+
+ @VisibleForTesting
+ boolean isVerticalReachabilityEnabled() {
+ return isVerticalReachabilityEnabled(mActivityRecord.getParent().getConfiguration());
+ }
+
+ boolean isLetterboxDoubleTapEducationEnabled() {
+ return isHorizontalReachabilityEnabled() || isVerticalReachabilityEnabled();
+ }
+
+ @AppCompatConfiguration.LetterboxVerticalReachabilityPosition
+ int getLetterboxPositionForVerticalReachability() {
+ final boolean isInFullScreenTabletopMode =
+ mAppCompatDeviceStateQuery.isDisplayFullScreenAndSeparatingHinge();
+ return mAppCompatConfiguration.getLetterboxPositionForVerticalReachability(
+ isInFullScreenTabletopMode);
+ }
+
+ @AppCompatConfiguration.LetterboxHorizontalReachabilityPosition
+ int getLetterboxPositionForHorizontalReachability() {
+ final boolean isInFullScreenBookMode = isFullScreenAndBookModeEnabled();
+ return mAppCompatConfiguration.getLetterboxPositionForHorizontalReachability(
+ isInFullScreenBookMode);
+ }
+
+ int getLetterboxPositionForLogging() {
+ int positionToLog = APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__UNKNOWN_POSITION;
+ if (isHorizontalReachabilityEnabled()) {
+ int letterboxPositionForHorizontalReachability = mAppCompatConfiguration
+ .getLetterboxPositionForHorizontalReachability(mAppCompatDeviceStateQuery
+ .isDisplayFullScreenAndInPosture(/* isTabletop */ false));
+ positionToLog = letterboxHorizontalReachabilityPositionToLetterboxPositionForLogging(
+ letterboxPositionForHorizontalReachability);
+ } else if (isVerticalReachabilityEnabled()) {
+ int letterboxPositionForVerticalReachability = mAppCompatConfiguration
+ .getLetterboxPositionForVerticalReachability(mAppCompatDeviceStateQuery
+ .isDisplayFullScreenAndInPosture(/* isTabletop */ true));
+ positionToLog = letterboxVerticalReachabilityPositionToLetterboxPositionForLogging(
+ letterboxPositionForVerticalReachability);
+ }
+ return positionToLog;
+ }
+
+ /**
+ * @return {@value true} if the vertical reachability should be allowed in case of
+ * thin letterboxing.
+ */
+ boolean allowVerticalReachabilityForThinLetterbox() {
+ if (!Flags.disableThinLetterboxingPolicy()) {
+ return true;
+ }
+ // When the flag is enabled we allow vertical reachability only if the
+ // app is not thin letterboxed vertically.
+ return !isVerticalThinLetterboxed();
+ }
+
+ /**
+ * @return {@value true} if the horizontal reachability should be enabled in case of
+ * thin letterboxing.
+ */
+ boolean allowHorizontalReachabilityForThinLetterbox() {
+ if (!Flags.disableThinLetterboxingPolicy()) {
+ return true;
+ }
+ // When the flag is enabled we allow horizontal reachability only if the
+ // app is not thin pillarboxed.
+ return !isHorizontalThinLetterboxed();
+ }
+
+ /**
+ * @return {@value true} if the resulting app is letterboxed in a way defined as thin.
+ */
+ boolean isVerticalThinLetterboxed() {
+ final int thinHeight = mAppCompatConfiguration.getThinLetterboxHeightPx();
+ if (thinHeight < 0) {
+ return false;
+ }
+ final Task task = mActivityRecord.getTask();
+ if (task == null) {
+ return false;
+ }
+ final int padding = Math.abs(
+ task.getBounds().height() - mActivityRecord.getBounds().height()) / 2;
+ return padding <= thinHeight;
+ }
+
+ /**
+ * @return {@value true} if the resulting app is pillarboxed in a way defined as thin.
+ */
+ boolean isHorizontalThinLetterboxed() {
+ final int thinWidth = mAppCompatConfiguration.getThinLetterboxWidthPx();
+ if (thinWidth < 0) {
+ return false;
+ }
+ final Task task = mActivityRecord.getTask();
+ if (task == null) {
+ return false;
+ }
+ final int padding = Math.abs(
+ task.getBounds().width() - mActivityRecord.getBounds().width()) / 2;
+ return padding <= thinWidth;
+ }
+
+ // Note that we check the task rather than the parent as with ActivityEmbedding the parent might
+ // be a TaskFragment, and its windowing mode is always MULTI_WINDOW, even if the task is
+ // actually fullscreen.
+ private boolean isDisplayFullScreenAndSeparatingHinge() {
+ Task task = mActivityRecord.getTask();
+ return mActivityRecord.mDisplayContent != null
+ && mActivityRecord.mDisplayContent.getDisplayRotation().isDisplaySeparatingHinge()
+ && task != null
+ && task.getWindowingMode() == WINDOWING_MODE_FULLSCREEN;
+ }
+
+ private int letterboxHorizontalReachabilityPositionToLetterboxPositionForLogging(
+ @AppCompatConfiguration.LetterboxHorizontalReachabilityPosition int position) {
+ switch (position) {
+ case LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT:
+ return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__LEFT;
+ case LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER:
+ return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__CENTER;
+ case LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT:
+ return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__RIGHT;
+ default:
+ throw new AssertionError(
+ "Unexpected letterbox horizontal reachability position type: "
+ + position);
+ }
+ }
+
+ private int letterboxVerticalReachabilityPositionToLetterboxPositionForLogging(
+ @AppCompatConfiguration.LetterboxVerticalReachabilityPosition int position) {
+ switch (position) {
+ case LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP:
+ return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__TOP;
+ case LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER:
+ return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__CENTER;
+ case LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM:
+ return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__BOTTOM;
+ default:
+ throw new AssertionError(
+ "Unexpected letterbox vertical reachability position type: "
+ + position);
+ }
+ }
+
+ private boolean isFullScreenAndBookModeEnabled() {
+ return mAppCompatDeviceStateQuery.isDisplayFullScreenAndInPosture(/* isTabletop */ false)
+ && mAppCompatConfiguration.getIsAutomaticReachabilityInBookModeEnabled();
+ }
+
+ /**
+ * Whether horizontal reachability is enabled for an activity in the current configuration.
+ *
+ * <p>Conditions that needs to be met:
+ * <ul>
+ * <li>Windowing mode is fullscreen.
+ * <li>Horizontal Reachability is enabled.
+ * <li>First top opaque activity fills parent vertically, but not horizontally.
+ * </ul>
+ */
+ private boolean isHorizontalReachabilityEnabled(@NonNull Configuration parentConfiguration) {
+ if (!allowHorizontalReachabilityForThinLetterbox()) {
+ return false;
+ }
+ final Rect parentAppBoundsOverride = mActivityRecord.getParentAppBoundsOverride();
+ final Rect parentAppBounds = parentAppBoundsOverride != null
+ ? parentAppBoundsOverride : parentConfiguration.windowConfiguration.getAppBounds();
+ // Use screen resolved bounds which uses resolved bounds or size compat bounds
+ // as activity bounds can sometimes be empty
+ final Rect opaqueActivityBounds = mActivityRecord.mAppCompatController
+ .getTransparentPolicy().getFirstOpaqueActivity()
+ .map(ActivityRecord::getScreenResolvedBounds)
+ .orElse(mActivityRecord.getScreenResolvedBounds());
+ return mAppCompatConfiguration.getIsHorizontalReachabilityEnabled()
+ && parentConfiguration.windowConfiguration.getWindowingMode()
+ == WINDOWING_MODE_FULLSCREEN
+ // Check whether the activity fills the parent vertically.
+ && parentAppBounds.height() <= opaqueActivityBounds.height()
+ && parentAppBounds.width() > opaqueActivityBounds.width();
+ }
+
+ /**
+ * Whether vertical reachability is enabled for an activity in the current configuration.
+ *
+ * <p>Conditions that needs to be met:
+ * <ul>
+ * <li>Windowing mode is fullscreen.
+ * <li>Vertical Reachability is enabled.
+ * <li>First top opaque activity fills parent horizontally but not vertically.
+ * </ul>
+ */
+ private boolean isVerticalReachabilityEnabled(@NonNull Configuration parentConfiguration) {
+ if (!allowVerticalReachabilityForThinLetterbox()) {
+ return false;
+ }
+ final Rect parentAppBoundsOverride = mActivityRecord.getParentAppBoundsOverride();
+ final Rect parentAppBounds = parentAppBoundsOverride != null
+ ? parentAppBoundsOverride : parentConfiguration.windowConfiguration.getAppBounds();
+ // Use screen resolved bounds which uses resolved bounds or size compat bounds
+ // as activity bounds can sometimes be empty.
+ final Rect opaqueActivityBounds = mActivityRecord.mAppCompatController
+ .getTransparentPolicy().getFirstOpaqueActivity()
+ .map(ActivityRecord::getScreenResolvedBounds)
+ .orElse(mActivityRecord.getScreenResolvedBounds());
+ return mAppCompatConfiguration.getIsVerticalReachabilityEnabled()
+ && parentConfiguration.windowConfiguration.getWindowingMode()
+ == WINDOWING_MODE_FULLSCREEN
+ // Check whether the activity fills the parent horizontally.
+ && parentAppBounds.width() <= opaqueActivityBounds.width()
+ && parentAppBounds.height() > opaqueActivityBounds.height();
+ }
+
+ private static class ReachabilityState {
+ // If the current event is a double tap.
+ private boolean mIsDoubleTapEvent;
+
+ boolean isFromDoubleTap() {
+ final boolean isFromDoubleTap = mIsDoubleTapEvent;
+ mIsDoubleTapEvent = false;
+ return isFromDoubleTap;
+ }
+ }
+
+}
diff --git a/services/core/java/com/android/server/wm/AppCompatReachabilityPolicy.java b/services/core/java/com/android/server/wm/AppCompatReachabilityPolicy.java
new file mode 100644
index 0000000..90bfddb
--- /dev/null
+++ b/services/core/java/com/android/server/wm/AppCompatReachabilityPolicy.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__BOTTOM_TO_CENTER;
+import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_BOTTOM;
+import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_LEFT;
+import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_RIGHT;
+import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_TOP;
+import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__LEFT_TO_CENTER;
+import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__RIGHT_TO_CENTER;
+import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__TOP_TO_CENTER;
+import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER;
+import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.Rect;
+
+import java.util.function.Supplier;
+
+/**
+ * Encapsulate logic about app compat reachability.
+ */
+class AppCompatReachabilityPolicy {
+
+ @NonNull
+ private final ActivityRecord mActivityRecord;
+ @NonNull
+ private final AppCompatConfiguration mAppCompatConfiguration;
+ @Nullable
+ private Supplier<Rect> mLetterboxInnerBoundsSupplier;
+
+ AppCompatReachabilityPolicy(@NonNull ActivityRecord activityRecord,
+ @NonNull AppCompatConfiguration appCompatConfiguration) {
+ mActivityRecord = activityRecord;
+ mAppCompatConfiguration = appCompatConfiguration;
+ }
+
+ /**
+ * To handle reachability a supplier for the current letterox inner bounds is required.
+ * <p/>
+ * @param letterboxInnerBoundsSupplier The supplier for the letterbox inner bounds.
+ */
+ void setLetterboxInnerBoundsSupplier(@Nullable Supplier<Rect> letterboxInnerBoundsSupplier) {
+ mLetterboxInnerBoundsSupplier = letterboxInnerBoundsSupplier;
+ }
+
+ /**
+ * Handles double tap events for reachability.
+ * <p/>
+ * @param x Double tap x coordinate.
+ * @param y Double tap y coordinate.
+ */
+ void handleDoubleTap(int x, int y) {
+ handleHorizontalDoubleTap(x);
+ handleVerticalDoubleTap(y);
+ }
+
+ private void handleHorizontalDoubleTap(int x) {
+ final AppCompatReachabilityOverrides reachabilityOverrides =
+ mActivityRecord.mAppCompatController.getAppCompatReachabilityOverrides();
+ if (!reachabilityOverrides.isHorizontalReachabilityEnabled()
+ || mActivityRecord.isInTransition()) {
+ return;
+ }
+ final Rect letterboxInnerFrame = getLetterboxInnerFrame();
+ if (letterboxInnerFrame.left <= x && letterboxInnerFrame.right >= x) {
+ // Only react to clicks at the sides of the letterboxed app window.
+ return;
+ }
+ final AppCompatDeviceStateQuery deviceStateQuery = mActivityRecord.mAppCompatController
+ .getAppCompatDeviceStateQuery();
+ final boolean isInFullScreenBookMode = deviceStateQuery
+ .isDisplayFullScreenAndSeparatingHinge()
+ && mAppCompatConfiguration.getIsAutomaticReachabilityInBookModeEnabled();
+ final int letterboxPositionForHorizontalReachability = mAppCompatConfiguration
+ .getLetterboxPositionForHorizontalReachability(isInFullScreenBookMode);
+ if (letterboxInnerFrame.left > x) {
+ // Moving to the next stop on the left side of the app window: right > center > left.
+ mAppCompatConfiguration.movePositionForHorizontalReachabilityToNextLeftStop(
+ isInFullScreenBookMode);
+ int letterboxPositionChangeForLog =
+ letterboxPositionForHorizontalReachability
+ == LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER
+ ? LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_LEFT
+ : LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__RIGHT_TO_CENTER;
+ logLetterboxPositionChange(letterboxPositionChangeForLog);
+ reachabilityOverrides.setDoubleTapEvent();
+ } else if (letterboxInnerFrame.right < x) {
+ // Moving to the next stop on the right side of the app window: left > center > right.
+ mAppCompatConfiguration.movePositionForHorizontalReachabilityToNextRightStop(
+ isInFullScreenBookMode);
+ final int letterboxPositionChangeForLog =
+ letterboxPositionForHorizontalReachability
+ == LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER
+ ? LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_RIGHT
+ : LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__LEFT_TO_CENTER;
+ logLetterboxPositionChange(letterboxPositionChangeForLog);
+ reachabilityOverrides.setDoubleTapEvent();
+ }
+ // TODO(197549949): Add animation for transition.
+ mActivityRecord.recomputeConfiguration();
+ }
+
+ private void handleVerticalDoubleTap(int y) {
+ final AppCompatReachabilityOverrides reachabilityOverrides =
+ mActivityRecord.mAppCompatController.getAppCompatReachabilityOverrides();
+ if (!reachabilityOverrides.isVerticalReachabilityEnabled()
+ || mActivityRecord.isInTransition()) {
+ return;
+ }
+ final Rect letterboxInnerFrame = getLetterboxInnerFrame();
+ if (letterboxInnerFrame.top <= y && letterboxInnerFrame.bottom >= y) {
+ // Only react to clicks at the top and bottom of the letterboxed app window.
+ return;
+ }
+ final AppCompatDeviceStateQuery deviceStateQuery = mActivityRecord.mAppCompatController
+ .getAppCompatDeviceStateQuery();
+ final boolean isInFullScreenTabletopMode = deviceStateQuery
+ .isDisplayFullScreenAndSeparatingHinge();
+ final int letterboxPositionForVerticalReachability = mAppCompatConfiguration
+ .getLetterboxPositionForVerticalReachability(isInFullScreenTabletopMode);
+ if (letterboxInnerFrame.top > y) {
+ // Moving to the next stop on the top side of the app window: bottom > center > top.
+ mAppCompatConfiguration.movePositionForVerticalReachabilityToNextTopStop(
+ isInFullScreenTabletopMode);
+ final int letterboxPositionChangeForLog =
+ letterboxPositionForVerticalReachability
+ == LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER
+ ? LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_TOP
+ : LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__BOTTOM_TO_CENTER;
+ logLetterboxPositionChange(letterboxPositionChangeForLog);
+ reachabilityOverrides.setDoubleTapEvent();
+ } else if (letterboxInnerFrame.bottom < y) {
+ // Moving to the next stop on the bottom side of the app window: top > center > bottom.
+ mAppCompatConfiguration.movePositionForVerticalReachabilityToNextBottomStop(
+ isInFullScreenTabletopMode);
+ final int letterboxPositionChangeForLog =
+ letterboxPositionForVerticalReachability
+ == LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER
+ ? LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_BOTTOM
+ : LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__TOP_TO_CENTER;
+ logLetterboxPositionChange(letterboxPositionChangeForLog);
+ reachabilityOverrides.setDoubleTapEvent();
+ }
+ // TODO(197549949): Add animation for transition.
+ mActivityRecord.recomputeConfiguration();
+ }
+
+ /**
+ * Logs letterbox position changes via {@link ActivityMetricsLogger#logLetterboxPositionChange}.
+ */
+ private void logLetterboxPositionChange(int letterboxPositionChangeForLog) {
+ mActivityRecord.mTaskSupervisor.getActivityMetricsLogger()
+ .logLetterboxPositionChange(mActivityRecord, letterboxPositionChangeForLog);
+ }
+
+ @NonNull
+ private Rect getLetterboxInnerFrame() {
+ return mLetterboxInnerBoundsSupplier != null ? mLetterboxInnerBoundsSupplier.get()
+ : new Rect();
+ }
+}
diff --git a/services/core/java/com/android/server/wm/AppCompatUtils.java b/services/core/java/com/android/server/wm/AppCompatUtils.java
index fd816067..a5db904 100644
--- a/services/core/java/com/android/server/wm/AppCompatUtils.java
+++ b/services/core/java/com/android/server/wm/AppCompatUtils.java
@@ -19,7 +19,13 @@
import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
+import static com.android.server.wm.ActivityRecord.State.RESUMED;
+
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.AppCompatTaskInfo;
+import android.app.CameraCompatTaskInfo;
+import android.app.TaskInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -57,7 +63,7 @@
/**
* Returns the aspect ratio of the given {@code rect}.
*/
- static float computeAspectRatio(Rect rect) {
+ static float computeAspectRatio(@NonNull Rect rect) {
final int width = rect.width();
final int height = rect.height();
if (width == 0 || height == 0) {
@@ -82,4 +88,123 @@
static boolean isChangeEnabled(@NonNull ActivityRecord activityRecord, long overrideChangeId) {
return activityRecord.info.isChangeEnabled(overrideChangeId);
}
+
+ /**
+ * Attempts to return the app bounds (bounds without insets) of the top most opaque activity. If
+ * these are not available, it defaults to the bounds of the activity which include insets. In
+ * the event the activity is in Size Compat Mode, the Size Compat bounds are returned instead.
+ */
+ @NonNull
+ static Rect getAppBounds(@NonNull ActivityRecord activityRecord) {
+ // TODO(b/268458693): Refactor configuration inheritance in case of translucent activities
+ final Rect appBounds = activityRecord.getConfiguration().windowConfiguration.getAppBounds();
+ if (appBounds == null) {
+ return activityRecord.getBounds();
+ }
+ return activityRecord.mAppCompatController.getTransparentPolicy()
+ .findOpaqueNotFinishingActivityBelow()
+ .map(AppCompatUtils::getAppBounds)
+ .orElseGet(() -> {
+ if (activityRecord.hasSizeCompatBounds()) {
+ return activityRecord.getScreenResolvedBounds();
+ }
+ return appBounds;
+ });
+ }
+
+ static void fillAppCompatTaskInfo(@NonNull Task task, @NonNull TaskInfo info,
+ @Nullable ActivityRecord top) {
+ final AppCompatTaskInfo appCompatTaskInfo = info.appCompatTaskInfo;
+ appCompatTaskInfo.cameraCompatTaskInfo.freeformCameraCompatMode =
+ CameraCompatTaskInfo.CAMERA_COMPAT_FREEFORM_NONE;
+ if (top == null) {
+ return;
+ }
+ final AppCompatReachabilityOverrides reachabilityOverrides = top.mAppCompatController
+ .getAppCompatReachabilityOverrides();
+ final boolean isTopActivityResumed = top.getOrganizedTask() == task && top.isState(RESUMED);
+ final boolean isTopActivityVisible = top.getOrganizedTask() == task && top.isVisible();
+ // Whether the direct top activity is in size compat mode.
+ appCompatTaskInfo.topActivityInSizeCompat = isTopActivityVisible && top.inSizeCompatMode();
+ if (appCompatTaskInfo.topActivityInSizeCompat
+ && top.mWmService.mAppCompatConfiguration.isTranslucentLetterboxingEnabled()) {
+ // We hide the restart button in case of transparent activities.
+ appCompatTaskInfo.topActivityInSizeCompat = top.fillsParent();
+ }
+ // Whether the direct top activity is eligible for letterbox education.
+ appCompatTaskInfo.topActivityEligibleForLetterboxEducation = isTopActivityResumed
+ && top.isEligibleForLetterboxEducation();
+ appCompatTaskInfo.isLetterboxEducationEnabled = top.mLetterboxUiController
+ .isLetterboxEducationEnabled();
+
+ appCompatTaskInfo.isUserFullscreenOverrideEnabled = top.mAppCompatController
+ .getAppCompatAspectRatioOverrides().shouldApplyUserFullscreenOverride();
+ appCompatTaskInfo.isSystemFullscreenOverrideEnabled = top.mAppCompatController
+ .getAppCompatAspectRatioOverrides().isSystemOverrideToFullscreenEnabled();
+
+ appCompatTaskInfo.isFromLetterboxDoubleTap = reachabilityOverrides.isFromDoubleTap();
+ final Rect bounds = top.getBounds();
+ final Rect appBounds = getAppBounds(top);
+ appCompatTaskInfo.topActivityLetterboxWidth = bounds.width();
+ appCompatTaskInfo.topActivityLetterboxHeight = bounds.height();
+ appCompatTaskInfo.topActivityLetterboxAppWidth = appBounds.width();
+ appCompatTaskInfo.topActivityLetterboxAppHeight = appBounds.height();
+
+ // We need to consider if letterboxed or pillarboxed.
+ // TODO(b/336807329) Encapsulate reachability logic
+ appCompatTaskInfo.isLetterboxDoubleTapEnabled = reachabilityOverrides
+ .isLetterboxDoubleTapEducationEnabled();
+ if (appCompatTaskInfo.isLetterboxDoubleTapEnabled) {
+ if (appCompatTaskInfo.isTopActivityPillarboxed()) {
+ if (reachabilityOverrides.allowHorizontalReachabilityForThinLetterbox()) {
+ // Pillarboxed.
+ appCompatTaskInfo.topActivityLetterboxHorizontalPosition =
+ reachabilityOverrides.getLetterboxPositionForHorizontalReachability();
+ } else {
+ appCompatTaskInfo.isLetterboxDoubleTapEnabled = false;
+ }
+ } else {
+ if (reachabilityOverrides.allowVerticalReachabilityForThinLetterbox()) {
+ // Letterboxed.
+ appCompatTaskInfo.topActivityLetterboxVerticalPosition =
+ reachabilityOverrides.getLetterboxPositionForVerticalReachability();
+ } else {
+ appCompatTaskInfo.isLetterboxDoubleTapEnabled = false;
+ }
+ }
+ }
+ appCompatTaskInfo.topActivityEligibleForUserAspectRatioButton =
+ !info.isTopActivityTransparent && !appCompatTaskInfo.topActivityInSizeCompat
+ && top.mAppCompatController.getAppCompatAspectRatioOverrides()
+ .shouldEnableUserAspectRatioSettings();
+ appCompatTaskInfo.topActivityBoundsLetterboxed = top.areBoundsLetterboxed();
+ appCompatTaskInfo.cameraCompatTaskInfo.freeformCameraCompatMode = top.mAppCompatController
+ .getAppCompatCameraOverrides().getFreeformCameraCompatMode();
+ }
+
+ /**
+ * Returns a string representing the reason for letterboxing. This method assumes the activity
+ * is letterboxed.
+ * @param activityRecord The {@link ActivityRecord} for the letterboxed activity.
+ * @param mainWin The {@link WindowState} used to letterboxing.
+ */
+ @NonNull
+ static String getLetterboxReasonString(@NonNull ActivityRecord activityRecord,
+ @NonNull WindowState mainWin) {
+ if (activityRecord.inSizeCompatMode()) {
+ return "SIZE_COMPAT_MODE";
+ }
+ final AppCompatAspectRatioPolicy aspectRatioPolicy = activityRecord.mAppCompatController
+ .getAppCompatAspectRatioPolicy();
+ if (aspectRatioPolicy.isLetterboxedForFixedOrientationAndAspectRatio()) {
+ return "FIXED_ORIENTATION";
+ }
+ if (mainWin.isLetterboxedForDisplayCutout()) {
+ return "DISPLAY_CUTOUT";
+ }
+ if (aspectRatioPolicy.isLetterboxedForAspectRatioOnly()) {
+ return "ASPECT_RATIO";
+ }
+ return "UNKNOWN_REASON";
+ }
}
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 78636a7..5a0cbf3 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -250,7 +250,7 @@
ArraySet<ActivityRecord> tmpOpenApps = mDisplayContent.mOpeningApps;
ArraySet<ActivityRecord> tmpCloseApps = mDisplayContent.mClosingApps;
- if (mDisplayContent.mAtmService.mBackNavigationController.isMonitoringTransition()) {
+ if (mDisplayContent.mAtmService.mBackNavigationController.isMonitoringFinishTransition()) {
tmpOpenApps = new ArraySet<>(mDisplayContent.mOpeningApps);
tmpCloseApps = new ArraySet<>(mDisplayContent.mClosingApps);
if (mDisplayContent.mAtmService.mBackNavigationController
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 0f8d68b..48e1079 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -24,6 +24,7 @@
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_NONE;
+import static android.view.WindowManager.TRANSIT_PREPARE_BACK_NAVIGATION;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BACK_PREVIEW;
@@ -47,6 +48,7 @@
import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.ArraySet;
+import android.util.Pair;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.RemoteAnimationTarget;
@@ -83,11 +85,6 @@
private AnimationHandler mAnimationHandler;
- /**
- * The transition who match the back navigation targets,
- * release animation after this transition finish.
- */
- private Transition mWaitTransitionFinish;
private final ArrayList<WindowContainer> mTmpOpenApps = new ArrayList<>();
private final ArrayList<WindowContainer> mTmpCloseApps = new ArrayList<>();
@@ -143,7 +140,7 @@
BackNavigationInfo.Builder infoBuilder = new BackNavigationInfo.Builder();
synchronized (wmService.mGlobalLock) {
- if (isMonitoringTransition()) {
+ if (isMonitoringFinishTransition()) {
Slog.w(TAG, "Previous animation hasn't finish, status: " + mAnimationHandler);
// Don't start any animation for it.
return null;
@@ -308,6 +305,7 @@
backType = BackNavigationInfo.TYPE_CALLBACK;
} else if (prevTask.isActivityTypeHome()) {
removedWindowContainer = currentTask;
+ prevTask = prevTask.getRootTask();
backType = BackNavigationInfo.TYPE_RETURN_TO_HOME;
final ActivityRecord ar = prevTask.getTopNonFinishingActivity();
mShowWallpaper = ar != null && ar.hasWallpaper();
@@ -562,10 +560,15 @@
return !prevActivities.isEmpty();
}
- boolean isMonitoringTransition() {
+ boolean isMonitoringFinishTransition() {
return mAnimationHandler.mComposed || mNavigationMonitor.isMonitorForRemote();
}
+ boolean isMonitoringPrepareTransition(Transition transition) {
+ return mAnimationHandler.mComposed
+ && mAnimationHandler.mOpenAnimAdaptor.mPreparedOpenTransition == transition;
+ }
+
private void scheduleAnimation(@NonNull AnimationHandler.ScheduleAnimationBuilder builder) {
mPendingAnimation = builder.build();
mWindowManagerService.mWindowPlacerLocked.requestTraversal();
@@ -576,7 +579,9 @@
}
private boolean isWaitBackTransition() {
- return mAnimationHandler.mComposed && mAnimationHandler.mWaitTransition;
+ // Ignore mWaitTransition while flag is enabled.
+ return mAnimationHandler.mComposed && (Flags.migratePredictiveBackTransition()
+ || mAnimationHandler.mWaitTransition);
}
boolean isKeyguardOccluded(WindowState focusWindow) {
@@ -626,7 +631,7 @@
*/
boolean removeIfContainsBackAnimationTargets(ArraySet<ActivityRecord> openApps,
ArraySet<ActivityRecord> closeApps) {
- if (!isMonitoringTransition()) {
+ if (!isMonitoringFinishTransition()) {
return false;
}
mTmpCloseApps.addAll(closeApps);
@@ -652,7 +657,6 @@
final ActivityRecord ar = openApps.valueAt(i);
if (mAnimationHandler.isTarget(ar, true /* open */)) {
openApps.removeAt(i);
- mAnimationHandler.markStartingSurfaceMatch(null /* reparentTransaction */);
}
}
for (int i = closeApps.size() - 1; i >= 0; --i) {
@@ -670,6 +674,12 @@
mAnimationHandler.markWindowHasDrawn(openActivity);
}
+ boolean isStartingSurfaceShown(ActivityRecord openActivity) {
+ if (!Flags.migratePredictiveBackTransition()) {
+ return false;
+ }
+ return mAnimationHandler.isStartingSurfaceDrawn(openActivity);
+ }
@VisibleForTesting
class NavigationMonitor {
// The window which triggering the back navigation.
@@ -767,8 +777,14 @@
* open or close list.
*/
void onTransactionReady(Transition transition, ArrayList<Transition.ChangeInfo> targets,
- SurfaceControl.Transaction startTransaction) {
- if (!isMonitoringTransition() || targets.isEmpty()) {
+ SurfaceControl.Transaction startTransaction,
+ SurfaceControl.Transaction finishTransaction) {
+ if (isMonitoringPrepareTransition(transition)) {
+ // Flag target matches and prepare to remove windowless surface.
+ mAnimationHandler.markStartingSurfaceMatch(startTransaction);
+ return;
+ }
+ if (!isMonitoringFinishTransition() || targets.isEmpty()) {
return;
}
if (mAnimationHandler.hasTargetDetached()) {
@@ -801,42 +817,40 @@
if (!matchAnimationTargets) {
mNavigationMonitor.onTransitionReadyWhileNavigate(mTmpOpenApps, mTmpCloseApps);
} else {
- if (mWaitTransitionFinish != null) {
+ if (mAnimationHandler.mPrepareCloseTransition != null) {
Slog.e(TAG, "Gesture animation is applied on another transition?");
}
- mWaitTransitionFinish = transition;
- // Flag target matches to defer remove the splash screen.
- for (int i = mTmpOpenApps.size() - 1; i >= 0; --i) {
- final WindowContainer wc = mTmpOpenApps.get(i);
- if (mAnimationHandler.isTarget(wc, true /* open */)) {
- mAnimationHandler.markStartingSurfaceMatch(startTransaction);
- break;
- }
+ mAnimationHandler.mPrepareCloseTransition = transition;
+ if (!Flags.migratePredictiveBackTransition()) {
+ // Because the target will reparent to transition root, so it cannot be controlled
+ // by animation leash. Hide the close target when transition starts.
+ startTransaction.hide(mAnimationHandler.mCloseAdaptor.mTarget.getSurfaceControl());
}
+ // Flag target matches and prepare to remove windowless surface.
+ mAnimationHandler.markStartingSurfaceMatch(startTransaction);
// release animation leash
if (mAnimationHandler.mOpenAnimAdaptor.mCloseTransaction != null) {
- startTransaction.merge(mAnimationHandler.mOpenAnimAdaptor.mCloseTransaction);
+ finishTransaction.merge(mAnimationHandler.mOpenAnimAdaptor.mCloseTransaction);
mAnimationHandler.mOpenAnimAdaptor.mCloseTransaction = null;
}
- // Because the target will reparent to transition root, so it cannot be controlled by
- // animation leash. Hide the close target when transition starts.
- startTransaction.hide(mAnimationHandler.mCloseAdaptor.mTarget.getSurfaceControl());
}
mTmpOpenApps.clear();
mTmpCloseApps.clear();
}
boolean isMonitorTransitionTarget(WindowContainer wc) {
- if (!isWaitBackTransition() || mWaitTransitionFinish == null) {
- return false;
+ if ((isWaitBackTransition() && mAnimationHandler.mPrepareCloseTransition != null)
+ || (mAnimationHandler.mOpenAnimAdaptor != null
+ && mAnimationHandler.mOpenAnimAdaptor.mPreparedOpenTransition != null)) {
+ return mAnimationHandler.isTarget(wc, wc.isVisibleRequested() /* open */);
}
- return mAnimationHandler.isTarget(wc, wc.isVisibleRequested() /* open */);
+ return false;
}
boolean shouldPauseTouch(WindowContainer wc) {
// Once the close transition is ready, it means the onBackInvoked callback has invoked, and
// app is ready to trigger next transition, no matter what it will be.
- return mAnimationHandler.mComposed && mWaitTransitionFinish == null
+ return mAnimationHandler.mComposed && mAnimationHandler.mPrepareCloseTransition == null
&& mAnimationHandler.isTarget(wc, wc.isVisibleRequested() /* open */);
}
@@ -847,7 +861,6 @@
void clearBackAnimations(boolean cancel) {
mAnimationHandler.clearBackAnimateTarget(cancel);
mNavigationMonitor.stopMonitorTransition();
- mWaitTransitionFinish = null;
}
/**
@@ -858,7 +871,13 @@
*/
void onTransitionFinish(ArrayList<Transition.ChangeInfo> targets,
@NonNull Transition finishedTransition) {
- if (finishedTransition == mWaitTransitionFinish) {
+ if (isMonitoringPrepareTransition(finishedTransition)) {
+ if (mAnimationHandler.mPrepareCloseTransition == null) {
+ clearBackAnimations(true /* cancel */);
+ }
+ return;
+ }
+ if (finishedTransition == mAnimationHandler.mPrepareCloseTransition) {
clearBackAnimations(false /* cancel */);
}
if (!mBackAnimationInProgress || mPendingAnimationBuilder == null) {
@@ -938,13 +957,13 @@
// the opening target like starting window do.
private boolean mStartingSurfaceTargetMatch;
private ActivityRecord[] mOpenActivities;
+ Transition mPrepareCloseTransition;
AnimationHandler(WindowManagerService wms) {
mWindowManagerService = wms;
final Context context = wms.mContext;
mShowWindowlessSurface = context.getResources().getBoolean(
- com.android.internal.R.bool.config_predictShowStartingSurface)
- && Flags.activitySnapshotByDefault();
+ com.android.internal.R.bool.config_predictShowStartingSurface);
}
private static final int UNKNOWN = 0;
private static final int TASK_SWITCH = 1;
@@ -982,6 +1001,12 @@
@NonNull ActivityRecord[] openingActivities) {
if (isActivitySwitch(close, open)) {
mSwitchType = ACTIVITY_SWITCH;
+ if (Flags.migratePredictiveBackTransition()) {
+ final Pair<WindowContainer, WindowContainer[]> replaced =
+ promoteToTFIfNeeded(close, open);
+ close = replaced.first;
+ open = replaced.second;
+ }
} else if (isTaskSwitch(close, open)) {
mSwitchType = TASK_SWITCH;
} else if (isDialogClose(close)) {
@@ -1019,6 +1044,34 @@
mOpenActivities = openingActivities;
}
+ private Pair<WindowContainer, WindowContainer[]> promoteToTFIfNeeded(
+ WindowContainer close, WindowContainer[] open) {
+ WindowContainer replaceClose = close;
+ TaskFragment closeTF = close.asActivityRecord().getTaskFragment();
+ if (closeTF != null && !closeTF.isEmbedded()) {
+ closeTF = null;
+ }
+ final WindowContainer[] replaceOpen = new WindowContainer[open.length];
+ if (open.length >= 2) { // Promote to TaskFragment
+ for (int i = open.length - 1; i >= 0; --i) {
+ replaceOpen[i] = open[i].asActivityRecord().getTaskFragment();
+ replaceClose = closeTF != null ? closeTF : close;
+ }
+ } else {
+ TaskFragment openTF = open[0].asActivityRecord().getTaskFragment();
+ if (openTF != null && !openTF.isEmbedded()) {
+ openTF = null;
+ }
+ if (closeTF != openTF) {
+ replaceOpen[0] = openTF != null ? openTF : open[0];
+ replaceClose = closeTF != null ? closeTF : close;
+ } else {
+ replaceOpen[0] = open[0];
+ }
+ }
+ return new Pair<>(replaceClose, replaceOpen);
+ }
+
private boolean composeAnimations(@NonNull WindowContainer close,
@NonNull WindowContainer[] open, @NonNull ActivityRecord[] openingActivities) {
if (mComposed || mWaitTransition) {
@@ -1080,7 +1133,8 @@
}
void markWindowHasDrawn(ActivityRecord activity) {
- if (!mComposed || mWaitTransition) {
+ if (!mComposed || mWaitTransition || mOpenAnimAdaptor.mPreparedOpenTransition == null
+ || mOpenAnimAdaptor.mRequestedStartingSurfaceId == INVALID_TASK_ID) {
return;
}
boolean allWindowDrawn = true;
@@ -1096,6 +1150,17 @@
}
}
+ boolean isStartingSurfaceDrawn(ActivityRecord activity) {
+ // Check whether we create windowless surface to prepare open transition
+ if (!mComposed || mOpenAnimAdaptor.mPreparedOpenTransition == null) {
+ return false;
+ }
+ if (isTarget(activity, true /* open */)) {
+ return mOpenAnimAdaptor.mStartingSurface != null;
+ }
+ return false;
+ }
+
private static boolean isAnimateTarget(@NonNull WindowContainer window,
@NonNull WindowContainer animationTarget, int switchType) {
if (switchType == TASK_SWITCH) {
@@ -1109,7 +1174,9 @@
&& window.hasChild(animationTarget));
} else if (switchType == ACTIVITY_SWITCH) {
return window == animationTarget
- || (window.asTaskFragment() != null && window.hasChild(animationTarget));
+ || (window.asTaskFragment() != null && window.hasChild(animationTarget))
+ || (animationTarget.asTaskFragment() != null
+ && animationTarget.hasChild(window));
}
return false;
}
@@ -1122,8 +1189,14 @@
resetActivity.mDisplayContent
.continueUpdateOrientationForDiffOrienLaunchingApp();
}
+ final Transition finishTransition =
+ resetActivity.mTransitionController.mFinishingTransition;
+ final boolean inFinishTransition = finishTransition != null
+ && (mPrepareCloseTransition == finishTransition
+ || (mOpenAnimAdaptor != null
+ && mOpenAnimAdaptor.mPreparedOpenTransition == finishTransition));
if (resetActivity.mLaunchTaskBehind) {
- restoreLaunchBehind(resetActivity, cancel);
+ restoreLaunchBehind(resetActivity, cancel, inFinishTransition);
}
}
}
@@ -1137,12 +1210,25 @@
}
}
- void markStartingSurfaceMatch(SurfaceControl.Transaction reparentTransaction) {
+ void markStartingSurfaceMatch(SurfaceControl.Transaction startTransaction) {
if (mStartingSurfaceTargetMatch) {
return;
}
mStartingSurfaceTargetMatch = true;
- mOpenAnimAdaptor.reparentWindowlessSurfaceToTarget(reparentTransaction);
+
+ if (mOpenAnimAdaptor.mRequestedStartingSurfaceId == INVALID_TASK_ID) {
+ return;
+ }
+ final SurfaceControl startingSurface = mOpenAnimAdaptor.mStartingSurface;
+ if (startingSurface != null && startingSurface.isValid()) {
+ startTransaction.addTransactionCommittedListener(Runnable::run, () -> {
+ synchronized (mWindowManagerService.mGlobalLock) {
+ if (mOpenAnimAdaptor != null) {
+ mOpenAnimAdaptor.cleanUpWindowlessSurface(true);
+ }
+ }
+ });
+ }
}
void clearBackAnimateTarget(boolean cancel) {
@@ -1150,6 +1236,7 @@
mComposed = false;
finishPresentAnimations(cancel);
}
+ mPrepareCloseTransition = null;
mWaitTransition = false;
mStartingSurfaceTargetMatch = false;
mSwitchType = UNKNOWN;
@@ -1239,6 +1326,9 @@
// requested one during animating.
private int mRequestedStartingSurfaceId = INVALID_TASK_ID;
private SurfaceControl mStartingSurface;
+
+ private Transition mPreparedOpenTransition;
+
BackWindowAnimationAdaptorWrapper(boolean isOpen, int switchType,
@NonNull WindowContainer... targets) {
mAdaptors = new BackWindowAnimationAdaptor[targets.length];
@@ -1267,6 +1357,8 @@
mCloseTransaction.apply();
mCloseTransaction = null;
}
+
+ mPreparedOpenTransition = null;
}
private RemoteAnimationTarget createWrapTarget() {
@@ -1279,8 +1371,7 @@
unionBounds.union(mAdaptors[i].mAnimationTarget.localBounds);
}
final WindowContainer wc = mAdaptors[0].mTarget;
- final Task task = wc.asActivityRecord() != null
- ? wc.asActivityRecord().getTask() : wc.asTask();
+ final Task task = mAdaptors[0].getTopTask();
final RemoteAnimationTarget represent = mAdaptors[0].mAnimationTarget;
final SurfaceControl leashSurface = new SurfaceControl.Builder()
.setName("cross-animation-leash")
@@ -1293,7 +1384,7 @@
mCloseTransaction = new SurfaceControl.Transaction();
mCloseTransaction.reparent(leashSurface, null);
final SurfaceControl.Transaction pt = wc.getPendingTransaction();
- pt.setLayer(leashSurface, wc.getParent().getLastLayer());
+ pt.setLayer(leashSurface, wc.getLastLayer());
for (int i = mAdaptors.length - 1; i >= 0; --i) {
BackWindowAnimationAdaptor adaptor = mAdaptors[i];
pt.reparent(adaptor.mAnimationTarget.leash, leashSurface);
@@ -1323,15 +1414,20 @@
}
final WindowContainer mainOpen = mAdaptors[0].mTarget;
final int switchType = mAdaptors[0].mSwitchType;
- final Task openTask = switchType == TASK_SWITCH
- ? mainOpen.asTask() : switchType == ACTIVITY_SWITCH
- ? mainOpen.asActivityRecord().getTask() : null;
+ final Task openTask = mAdaptors[0].getTopTask();
if (openTask == null) {
return;
}
- final ActivityRecord mainActivity = switchType == ACTIVITY_SWITCH
- ? mainOpen.asActivityRecord()
- : openTask.getTopNonFinishingActivity();
+ ActivityRecord mainActivity = null;
+ if (switchType == ACTIVITY_SWITCH) {
+ mainActivity = mainOpen.asActivityRecord();
+ if (mainActivity == null && mainOpen.asTaskFragment() != null) {
+ mainActivity = mainOpen.asTaskFragment().getTopNonFinishingActivity();
+ }
+ }
+ if (mainActivity == null) {
+ mainActivity = openTask.getTopNonFinishingActivity();
+ }
if (mainActivity == null) {
return;
}
@@ -1363,6 +1459,8 @@
synchronized (openTask.mWmService.mGlobalLock) {
if (mRequestedStartingSurfaceId != INVALID_TASK_ID) {
mStartingSurface = sc;
+ openTask.mWmService.mWindowPlacerLocked
+ .requestTraversal();
} else {
sc.release();
}
@@ -1371,28 +1469,6 @@
});
}
- // When back gesture has triggered and transition target matches navigation target,
- // reparent the starting surface to the opening target as it's starting window.
- void reparentWindowlessSurfaceToTarget(SurfaceControl.Transaction reparentTransaction) {
- if (mRequestedStartingSurfaceId == INVALID_TASK_ID) {
- return;
- }
- // If open target matches, reparent to open activity or task
- if (mStartingSurface != null && mStartingSurface.isValid()) {
- SurfaceControl.Transaction transaction = reparentTransaction != null
- ? reparentTransaction : mAdaptors[0].mTarget.getPendingTransaction();
- if (mAdaptors.length != 1) {
- // More than one opening window, reparent starting surface to leaf task.
- final WindowContainer wc = mAdaptors[0].mTarget;
- final Task task = wc.asActivityRecord() != null
- ? wc.asActivityRecord().getTask() : wc.asTask();
- transaction.reparent(mStartingSurface, task != null
- ? task.getSurfaceControl()
- : mAdaptors[0].mTarget.getSurfaceControl());
- }
- }
- }
-
/**
* Ask shell to clear the starting surface.
* @param openTransitionMatch if true, shell will play the remove starting window
@@ -1430,6 +1506,22 @@
mSwitchType = switchType;
}
+ Task getTopTask() {
+ final Task asTask = mTarget.asTask();
+ if (asTask != null) {
+ return asTask;
+ }
+ final ActivityRecord ar = mTarget.asActivityRecord();
+ if (ar != null) {
+ return ar.getTask();
+ }
+ final TaskFragment tf = mTarget.asTaskFragment();
+ if (tf != null) {
+ return tf.getTask();
+ }
+ return null;
+ }
+
@Override
public boolean getShowWallpaper() {
return false;
@@ -1619,9 +1711,8 @@
needsLaunchBehind = snapshot == null;
}
if (needsLaunchBehind) {
- for (int i = visibleOpenActivities.length - 1; i >= 0; --i) {
- setLaunchBehind(visibleOpenActivities[i]);
- }
+ openAnimationAdaptor.mPreparedOpenTransition =
+ setLaunchBehind(visibleOpenActivities);
}
// Force update mLastSurfaceShowing for opening activity and its task.
if (mWindowManagerService.mRoot.mTransitionController.isShellTransitionsEnabled()) {
@@ -1677,13 +1768,22 @@
// animation was canceled
return;
}
- if (!triggerBack) {
- clearBackAnimateTarget(true /* cancel */);
+ if (Flags.migratePredictiveBackTransition()) {
+ if (mOpenAnimAdaptor == null
+ || mOpenAnimAdaptor.mPreparedOpenTransition == null) {
+ // no open nor close transition, this is window animation
+ if (!triggerBack) {
+ clearBackAnimateTarget(true /* cancel */);
+ }
+ }
} else {
- mWaitTransition = true;
+ if (!triggerBack) {
+ clearBackAnimateTarget(true /* cancel */);
+ } else {
+ mWaitTransition = true;
+ }
}
}
- // TODO Add timeout monitor if transition didn't happen
}
};
}
@@ -1740,28 +1840,75 @@
return openActivities;
}
- private static void setLaunchBehind(@NonNull ActivityRecord activity) {
- if (!activity.isVisibleRequested()) {
- // The transition could commit the visibility and in the finishing state, that could
- // skip commitVisibility call in setVisibility cause the activity won't visible here.
- // Call it again to make sure the activity could be visible while handling the pending
- // animation.
- // Do not performLayout during prepare animation, because it could cause focus window
- // change. Let that happen after the BackNavigationInfo has returned to shell.
- activity.commitVisibility(true, false /* performLayout */);
+ private static Transition setLaunchBehind(@NonNull ActivityRecord[] activities) {
+ final boolean migrateBackTransition = Flags.migratePredictiveBackTransition();
+ final ArrayList<ActivityRecord> affects = new ArrayList<>();
+ for (int i = activities.length - 1; i >= 0; --i) {
+ final ActivityRecord activity = activities[i];
+ if (activity.mLaunchTaskBehind || activity.isVisibleRequested()) {
+ continue;
+ }
+ affects.add(activity);
+ }
+ if (affects.isEmpty()) {
+ return null;
+ }
+
+ final TransitionController tc = activities[0].mTransitionController;
+ final Transition prepareOpen = migrateBackTransition && !tc.isCollecting()
+ ? tc.createTransition(TRANSIT_PREPARE_BACK_NAVIGATION) : null;
+
+ for (int i = affects.size() - 1; i >= 0; --i) {
+ final ActivityRecord activity = affects.get(i);
+ if (!migrateBackTransition && !activity.isVisibleRequested()) {
+ // The transition could commit the visibility and in the finishing state, that could
+ // skip commitVisibility call in setVisibility cause the activity won't visible
+ // here.
+ // Call it again to make sure the activity could be visible while handling the
+ // pending animation.
+ // Do not performLayout during prepare animation, because it could cause focus
+ // window change. Let that happen after the BackNavigationInfo has returned to
+ // shell.
+ activity.commitVisibility(true, false /* performLayout */);
+ }
activity.mTransitionController.mSnapshotController
.mActivitySnapshotController.addOnBackPressedActivity(activity);
- }
- activity.mLaunchTaskBehind = true;
+ activity.mLaunchTaskBehind = true;
- ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
- "Setting Activity.mLauncherTaskBehind to true. Activity=%s", activity);
- activity.mTaskSupervisor.mStoppingActivities.remove(activity);
- activity.getDisplayContent().ensureActivitiesVisible(null /* starting */,
- true /* notifyClients */);
+ ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
+ "Setting Activity.mLauncherTaskBehind to true. Activity=%s", activity);
+ activity.mTaskSupervisor.mStoppingActivities.remove(activity);
+
+ if (!migrateBackTransition) {
+ activity.getDisplayContent().ensureActivitiesVisible(null /* starting */,
+ true /* notifyClients */);
+ } else if (activity.shouldBeVisible()) {
+ activity.ensureActivityConfiguration(true /* ignoreVisibility */);
+ activity.makeVisibleIfNeeded(null /* starting */, true /* notifyToClient */);
+ }
+ }
+ boolean needTransition = false;
+ final DisplayContent dc = affects.get(0).getDisplayContent();
+ for (int i = affects.size() - 1; i >= 0; --i) {
+ final ActivityRecord activity = affects.get(i);
+ needTransition |= tc.isCollecting(activity);
+ }
+ if (prepareOpen != null) {
+ if (needTransition) {
+ tc.requestStartTransition(prepareOpen,
+ null /*startTask */, null /* remoteTransition */,
+ null /* displayChange */);
+ tc.setReady(dc);
+ return prepareOpen;
+ } else {
+ prepareOpen.abort();
+ }
+ }
+ return null;
}
- private static void restoreLaunchBehind(@NonNull ActivityRecord activity, boolean cancel) {
+ private static void restoreLaunchBehind(@NonNull ActivityRecord activity, boolean cancel,
+ boolean finishTransition) {
if (!activity.isAttached()) {
// The activity was detached from hierarchy.
return;
@@ -1771,9 +1918,15 @@
"Setting Activity.mLauncherTaskBehind to false. Activity=%s",
activity);
if (cancel) {
- // Restore the launch-behind state
- // TODO b/347168362 Change status directly during collecting for a transition.
- activity.mTaskSupervisor.scheduleLaunchTaskBehindComplete(activity.token);
+ final boolean migrateBackTransition = Flags.migratePredictiveBackTransition();
+ if (migrateBackTransition && finishTransition) {
+ activity.commitVisibility(false /* visible */, false /* performLayout */,
+ true /* fromTransition */);
+ } else {
+ // Restore the launch-behind state
+ // TODO b/347168362 Change status directly during collecting for a transition.
+ activity.mTaskSupervisor.scheduleLaunchTaskBehindComplete(activity.token);
+ }
// Ignore all change
activity.mTransitionController.mSnapshotController
.mActivitySnapshotController.clearOnBackPressedActivities();
@@ -1835,12 +1988,7 @@
&& ah.mSwitchType != AnimationHandler.ACTIVITY_SWITCH)) {
return;
}
- for (int i = mAnimationHandler.mOpenActivities.length - 1; i >= 0; --i) {
- final ActivityRecord preDrawActivity = mAnimationHandler.mOpenActivities[i];
- if (!preDrawActivity.mLaunchTaskBehind) {
- setLaunchBehind(preDrawActivity);
- }
- }
+ setLaunchBehind(mAnimationHandler.mOpenActivities);
}
}
}
@@ -1853,10 +2001,15 @@
snapshot = task.mRootWindowContainer.mWindowManager.mTaskSnapshotController.getSnapshot(
task.mTaskId, task.mUserId, false /* restoreFromDisk */,
false /* isLowResolution */);
- } else if (w.asActivityRecord() != null) {
- final ActivityRecord ar = w.asActivityRecord();
- snapshot = ar.mWmService.mSnapshotController.mActivitySnapshotController
- .getSnapshot(visibleOpenActivities);
+ } else {
+ ActivityRecord ar = w.asActivityRecord();
+ if (ar == null && w.asTaskFragment() != null) {
+ ar = w.asTaskFragment().getTopNonFinishingActivity();
+ }
+ if (ar != null) {
+ snapshot = ar.mWmService.mSnapshotController.mActivitySnapshotController
+ .getSnapshot(visibleOpenActivities);
+ }
}
return isSnapshotCompatible(snapshot, visibleOpenActivities) ? snapshot : null;
diff --git a/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java b/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java
index 9996bbc..3e55e2d 100644
--- a/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java
+++ b/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java
@@ -234,12 +234,13 @@
float desiredAspectRatio = 0;
if (taskInfo.isRunning) {
final AppCompatTaskInfo appCompatTaskInfo = taskInfo.appCompatTaskInfo;
+ final int appLetterboxWidth =
+ taskInfo.appCompatTaskInfo.topActivityLetterboxAppWidth;
+ final int appLetterboxHeight =
+ taskInfo.appCompatTaskInfo.topActivityLetterboxAppHeight;
if (appCompatTaskInfo.topActivityBoundsLetterboxed) {
- desiredAspectRatio = (float) Math.max(
- appCompatTaskInfo.topActivityLetterboxWidth,
- appCompatTaskInfo.topActivityLetterboxHeight)
- / Math.min(appCompatTaskInfo.topActivityLetterboxWidth,
- appCompatTaskInfo.topActivityLetterboxHeight);
+ desiredAspectRatio = (float) Math.max(appLetterboxWidth, appLetterboxHeight)
+ / Math.min(appLetterboxWidth, appLetterboxHeight);
} else {
desiredAspectRatio = Math.max(fullscreenHeight, fullscreenWidth)
/ Math.min(fullscreenHeight, fullscreenWidth);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b31ae90..9c8c759 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -4415,13 +4415,14 @@
mWmService.dispatchImeInputTargetVisibilityChanged(
targetWin.mClient.asBinder(), isVisibleRequested,
targetWin.mActivityRecord != null
- && targetWin.mActivityRecord.finishing);
+ && targetWin.mActivityRecord.finishing,
+ mDisplayId);
}
});
targetWin.mToken.registerWindowContainerListener(
mImeTargetTokenListenerPair.second);
mWmService.dispatchImeInputTargetVisibilityChanged(targetWin.mClient.asBinder(),
- targetWin.isVisible() /* visible */, false /* removed */);
+ targetWin.isVisible() /* visible */, false /* removed */, mDisplayId);
}
}
if (refreshImeSecureFlag(getPendingTransaction())) {
@@ -5081,9 +5082,11 @@
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
- // This should be called after the insets have been dispatched to clients and we have
- // committed finish drawing windows.
- mInsetsStateController.getImeSourceProvider().checkAndStartShowImePostLayout();
+ if (!android.view.inputmethod.Flags.refactorInsetsController()) {
+ // This should be called after the insets have been dispatched to clients and we have
+ // committed finish drawing windows.
+ mInsetsStateController.getImeSourceProvider().checkAndStartShowImePostLayout();
+ }
mLastHasContent = mTmpApplySurfaceChangesTransactionState.displayHasContent;
if (!inTransition() && !mDisplayRotation.isRotatingSeamlessly()) {
@@ -6266,7 +6269,7 @@
// by looping the children, so that we don't miss any root tasks after the children size
// changed or reordered.
final ArrayList<Task> rootTasks = new ArrayList<>();
- forAllRootTasks(rootTask -> {
+ getDefaultTaskDisplayArea().forAllRootTasks(rootTask -> {
for (int activityType : activityTypes) {
// Collect the root tasks that are currently being organized.
if (rootTask.mCreatedByOrganizer) {
diff --git a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java
index 4ec318b..dedf35a 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java
@@ -24,6 +24,7 @@
import android.companion.virtualdevice.flags.Flags;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.IntentSender;
import android.content.pm.ActivityInfo;
import android.os.Process;
import android.os.UserHandle;
@@ -34,6 +35,7 @@
import java.io.PrintWriter;
import java.util.List;
+import java.util.function.Supplier;
class DisplayWindowPolicyControllerHelper {
private static final String TAG = "DisplayWindowPolicyControllerHelper";
@@ -98,7 +100,8 @@
*/
public boolean canActivityBeLaunched(ActivityInfo activityInfo,
Intent intent, @WindowConfiguration.WindowingMode int windowingMode,
- int launchingFromDisplayId, boolean isNewTask) {
+ int launchingFromDisplayId, boolean isNewTask, boolean isResultExpected,
+ Supplier<IntentSender> intentSender) {
if (mDisplayWindowPolicyController == null) {
// Missing controller means that this display has no categories for activity launch
// restriction.
@@ -111,7 +114,7 @@
return true;
}
return mDisplayWindowPolicyController.canActivityBeLaunched(activityInfo, intent,
- windowingMode, launchingFromDisplayId, isNewTask);
+ windowingMode, launchingFromDisplayId, isNewTask, isResultExpected, intentSender);
}
private boolean hasDisplayCategory(ActivityInfo aInfo) {
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java b/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java
index 27e6e09..7135c3b 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java
@@ -44,7 +44,6 @@
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
import com.android.server.wm.DisplayWindowSettings.SettingsProvider;
-import com.android.window.flags.Flags;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -145,9 +144,6 @@
* @see #DATA_DISPLAY_SETTINGS_FILE_PATH
*/
void setOverrideSettingsForUser(@UserIdInt int userId) {
- if (!Flags.perUserDisplayWindowSettings()) {
- return;
- }
final AtomicFile settingsFile = getOverrideSettingsFileForUser(userId);
setOverrideSettingsStorage(new AtomicFileStorage(settingsFile));
}
@@ -165,9 +161,6 @@
*/
void removeStaleDisplaySettingsLocked(@NonNull WindowManagerService wms,
@NonNull RootWindowContainer root) {
- if (!Flags.perUserDisplayWindowSettings()) {
- return;
- }
final Set<String> displayIdentifiers = new ArraySet<>();
final Consumer<DisplayInfo> addDisplayIdentifier =
displayInfo -> displayIdentifiers.add(mOverrideSettings.getIdentifier(displayInfo));
@@ -403,12 +396,9 @@
@NonNull
private static AtomicFile getOverrideSettingsFileForUser(@UserIdInt int userId) {
- final File directory;
- if (userId == USER_SYSTEM || !Flags.perUserDisplayWindowSettings()) {
- directory = Environment.getDataDirectory();
- } else {
- directory = Environment.getDataSystemCeDirectory(userId);
- }
+ final File directory = (userId == USER_SYSTEM)
+ ? Environment.getDataDirectory()
+ : Environment.getDataSystemCeDirectory(userId);
final File overrideSettingsFile = new File(directory, DATA_DISPLAY_SETTINGS_FILE_PATH);
return new AtomicFile(overrideSettingsFile, WM_DISPLAY_COMMIT_TAG);
}
diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
index 4f4daa1..3a5f9b7 100644
--- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
@@ -105,6 +105,7 @@
ImeTracker.forLogging().onProgress(mStatsToken,
ImeTracker.PHASE_WM_POST_LAYOUT_NOTIFY_CONTROLS_CHANGED);
mStateController.notifyControlChanged(mControlTarget);
+ setImeShowing(true);
} else if (wasServerVisible && mServerVisible && mGivenInsetsReady
&& givenInsetsPending) {
// If the server visibility didn't change (still visible), and mGivenInsetsReady
@@ -113,6 +114,8 @@
ImeTracker.forLogging().onCancelled(mStatsToken,
ImeTracker.PHASE_WM_POST_LAYOUT_NOTIFY_CONTROLS_CHANGED);
mStatsToken = null;
+ } else if (wasServerVisible && !mServerVisible) {
+ setImeShowing(false);
}
}
}
diff --git a/services/core/java/com/android/server/wm/ImeTargetChangeListener.java b/services/core/java/com/android/server/wm/ImeTargetChangeListener.java
index 88b76aa..e94f17c 100644
--- a/services/core/java/com/android/server/wm/ImeTargetChangeListener.java
+++ b/services/core/java/com/android/server/wm/ImeTargetChangeListener.java
@@ -37,25 +37,27 @@
* @param visible the visibility of the overlay window, {@code true} means visible
* and {@code false} otherwise.
* @param removed Whether the IME target overlay window has being removed.
+ * @param displayId display ID where the overlay window exists.
*/
default void onImeTargetOverlayVisibilityChanged(@NonNull IBinder overlayWindowToken,
@WindowManager.LayoutParams.WindowType int windowType,
- boolean visible, boolean removed) {
+ boolean visible, boolean removed, int displayId) {
}
/**
* Called when the visibility of IME input target window has changed.
*
* @param imeInputTarget the window token of the IME input target window.
- * @param visible the new window visibility made by {@param imeInputTarget}. visible is
+ * @param visible the new window visibility made by {@code imeInputTarget}. visible is
* {@code true} when switching to the new visible IME input target
* window and started input, or the same input target relayout to
* visible from invisible. In contrast, visible is {@code false} when
* closing the input target, or the same input target relayout to
* invisible from visible.
* @param removed Whether the IME input target window has being removed.
+ * @param displayId display ID where the overlay window exists.
*/
default void onImeInputTargetVisibilityChanged(@NonNull IBinder imeInputTarget, boolean visible,
- boolean removed) {
+ boolean removed, int displayId) {
}
}
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index 2aa7c0c..3fc5eaf 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -40,7 +40,6 @@
import java.util.function.BooleanSupplier;
import java.util.function.DoubleSupplier;
-import java.util.function.IntConsumer;
import java.util.function.IntSupplier;
import java.util.function.Supplier;
@@ -76,9 +75,8 @@
// for overlaping an app window and letterbox surfaces.
private final LetterboxSurface mFullWindowSurface = new LetterboxSurface("fullWindow");
private final LetterboxSurface[] mSurfaces = { mLeft, mTop, mRight, mBottom };
- // Reachability gestures.
- private final IntConsumer mDoubleTapCallbackX;
- private final IntConsumer mDoubleTapCallbackY;
+ @NonNull
+ private final AppCompatReachabilityPolicy mAppCompatReachabilityPolicy;
/**
* Constructs a Letterbox.
@@ -92,8 +90,7 @@
BooleanSupplier hasWallpaperBackgroundSupplier,
IntSupplier blurRadiusSupplier,
DoubleSupplier darkScrimAlphaSupplier,
- IntConsumer doubleTapCallbackX,
- IntConsumer doubleTapCallbackY,
+ @NonNull AppCompatReachabilityPolicy appCompatReachabilityPolicy,
Supplier<SurfaceControl> parentSurface) {
mSurfaceControlFactory = surfaceControlFactory;
mTransactionFactory = transactionFactory;
@@ -102,9 +99,10 @@
mHasWallpaperBackgroundSupplier = hasWallpaperBackgroundSupplier;
mBlurRadiusSupplier = blurRadiusSupplier;
mDarkScrimAlphaSupplier = darkScrimAlphaSupplier;
- mDoubleTapCallbackX = doubleTapCallbackX;
- mDoubleTapCallbackY = doubleTapCallbackY;
+ mAppCompatReachabilityPolicy = appCompatReachabilityPolicy;
mParentSurfaceSupplier = parentSurface;
+ // TODO Remove after Letterbox refactoring.
+ mAppCompatReachabilityPolicy.setLetterboxInnerBoundsSupplier(this::getInnerFrame);
}
/**
@@ -290,8 +288,8 @@
// This check prevents late events to be handled in case the Letterbox has been
// already destroyed and so mOuter.isEmpty() is true.
if (!mOuter.isEmpty() && e.getAction() == MotionEvent.ACTION_UP) {
- mDoubleTapCallbackX.accept((int) e.getRawX());
- mDoubleTapCallbackY.accept((int) e.getRawY());
+ mAppCompatReachabilityPolicy.handleDoubleTap((int) e.getRawX(),
+ (int) e.getRawY());
return true;
}
return false;
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index 291eab1..38df1b0 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -16,43 +16,21 @@
package com.android.server.wm;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__BOTTOM;
-import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__CENTER;
-import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__LEFT;
-import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__RIGHT;
-import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__TOP;
-import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__UNKNOWN_POSITION;
-import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__BOTTOM_TO_CENTER;
-import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_BOTTOM;
-import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_LEFT;
-import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_RIGHT;
-import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_TOP;
-import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__LEFT_TO_CENTER;
-import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__RIGHT_TO_CENTER;
-import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__TOP_TO_CENTER;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND;
import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING;
import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_SOLID_COLOR;
import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_WALLPAPER;
-import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER;
-import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT;
-import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT;
-import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM;
-import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER;
-import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP;
import static com.android.server.wm.AppCompatConfiguration.letterboxBackgroundTypeToString;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager.TaskDescription;
-import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
@@ -68,7 +46,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.LetterboxDetails;
import com.android.server.wm.AppCompatConfiguration.LetterboxBackgroundType;
-import com.android.window.flags.Flags;
import java.io.PrintWriter;
@@ -85,6 +62,16 @@
private final ActivityRecord mActivityRecord;
+ // TODO(b/356385137): Remove these we added to make dependencies temporarily explicit.
+ @NonNull
+ private final AppCompatReachabilityOverrides mAppCompatReachabilityOverrides;
+ @NonNull
+ private final AppCompatReachabilityPolicy mAppCompatReachabilityPolicy;
+ @NonNull
+ private final TransparentPolicy mTransparentPolicy;
+ @NonNull
+ private final AppCompatOrientationOverrides mAppCompatOrientationOverrides;
+
private boolean mShowWallpaperForLetterboxBackground;
@Nullable
@@ -92,14 +79,21 @@
private boolean mLastShouldShowLetterboxUi;
- private boolean mDoubleTapEvent;
-
LetterboxUiController(WindowManagerService wmService, ActivityRecord activityRecord) {
mAppCompatConfiguration = wmService.mAppCompatConfiguration;
// Given activityRecord may not be fully constructed since LetterboxUiController
// is created in its constructor. It shouldn't be used in this constructor but it's safe
// to use it after since controller is only used in ActivityRecord.
mActivityRecord = activityRecord;
+ // TODO(b/356385137): Remove these we added to make dependencies temporarily explicit.
+ mAppCompatReachabilityOverrides = mActivityRecord.mAppCompatController
+ .getAppCompatReachabilityOverrides();
+ mAppCompatReachabilityPolicy = mActivityRecord.mAppCompatController
+ .getAppCompatReachabilityPolicy();
+ mTransparentPolicy = mActivityRecord.mAppCompatController.getTransparentPolicy();
+ mAppCompatOrientationOverrides = mActivityRecord.mAppCompatController
+ .getAppCompatOrientationOverrides();
+
}
/** Cleans up {@link Letterbox} if it exists.*/
@@ -107,6 +101,8 @@
if (mLetterbox != null) {
mLetterbox.destroy();
mLetterbox = null;
+ // TODO Remove after Letterbox refactoring.
+ mAppCompatReachabilityPolicy.setLetterboxInnerBoundsSupplier(null);
}
}
@@ -190,8 +186,7 @@
this::hasWallpaperBackgroundForLetterbox,
this::getLetterboxWallpaperBlurRadiusPx,
this::getLetterboxWallpaperDarkScrimAlpha,
- this::handleHorizontalDoubleTap,
- this::handleVerticalDoubleTap,
+ mAppCompatReachabilityPolicy,
this::getLetterboxParentSurface);
mLetterbox.attachInput(w);
}
@@ -227,11 +222,10 @@
// For this reason we use ActivityRecord#getBounds() that the translucent activity
// inherits from the first opaque activity beneath and also takes care of the scaling
// in case of activities in size compat mode.
- final Rect innerFrame = mActivityRecord.mAppCompatController
- .getTransparentPolicy().isRunning()
- ? mActivityRecord.getBounds() : w.getFrame();
+ final Rect innerFrame =
+ mTransparentPolicy.isRunning() ? mActivityRecord.getBounds() : w.getFrame();
mLetterbox.layout(spaceToFill, innerFrame, mTmpPoint);
- if (mDoubleTapEvent) {
+ if (mAppCompatReachabilityOverrides.isDoubleTapEvent()) {
// We need to notify Shell that letterbox position has changed.
mActivityRecord.getTask().dispatchTaskInfoChangedIfNeeded(true /* force */);
}
@@ -240,12 +234,6 @@
}
}
- boolean isFromDoubleTap() {
- final boolean isFromDoubleTap = mDoubleTapEvent;
- mDoubleTapEvent = false;
- return isFromDoubleTap;
- }
-
SurfaceControl getLetterboxParentSurface() {
if (mActivityRecord.isInLetterboxAnimation()) {
return mActivityRecord.getTask().getSurfaceControl();
@@ -272,310 +260,13 @@
&& mActivityRecord.fillsParent();
}
- // Check if we are in the given pose and in fullscreen mode.
- // Note that we check the task rather than the parent as with ActivityEmbedding the parent might
- // be a TaskFragment, and its windowing mode is always MULTI_WINDOW, even if the task is
- // actually fullscreen. If display is still in transition e.g. unfolding, don't return true
- // for HALF_FOLDED state or app will flicker.
- boolean isDisplayFullScreenAndInPosture(boolean isTabletop) {
- Task task = mActivityRecord.getTask();
- return mActivityRecord.mDisplayContent != null && task != null
- && mActivityRecord.mDisplayContent.getDisplayRotation().isDeviceInPosture(
- DeviceStateController.DeviceState.HALF_FOLDED, isTabletop)
- && !mActivityRecord.mDisplayContent.inTransition()
- && task.getWindowingMode() == WINDOWING_MODE_FULLSCREEN;
- }
-
- // Note that we check the task rather than the parent as with ActivityEmbedding the parent might
- // be a TaskFragment, and its windowing mode is always MULTI_WINDOW, even if the task is
- // actually fullscreen.
- private boolean isDisplayFullScreenAndSeparatingHinge() {
- Task task = mActivityRecord.getTask();
- return mActivityRecord.mDisplayContent != null
- && mActivityRecord.mDisplayContent.getDisplayRotation().isDisplaySeparatingHinge()
- && task != null
- && task.getWindowingMode() == WINDOWING_MODE_FULLSCREEN;
- }
-
-
- float getHorizontalPositionMultiplier(Configuration parentConfiguration) {
- // Don't check resolved configuration because it may not be updated yet during
- // configuration change.
- boolean bookModeEnabled = isFullScreenAndBookModeEnabled();
- return isHorizontalReachabilityEnabled(parentConfiguration)
- // Using the last global dynamic position to avoid "jumps" when moving
- // between apps or activities.
- ? mAppCompatConfiguration.getHorizontalMultiplierForReachability(bookModeEnabled)
- : mAppCompatConfiguration.getLetterboxHorizontalPositionMultiplier(bookModeEnabled);
- }
-
- private boolean isFullScreenAndBookModeEnabled() {
- return isDisplayFullScreenAndInPosture(/* isTabletop */ false)
- && mAppCompatConfiguration.getIsAutomaticReachabilityInBookModeEnabled();
- }
-
- float getVerticalPositionMultiplier(Configuration parentConfiguration) {
- // Don't check resolved configuration because it may not be updated yet during
- // configuration change.
- boolean tabletopMode = isDisplayFullScreenAndInPosture(/* isTabletop */ true);
- return isVerticalReachabilityEnabled(parentConfiguration)
- // Using the last global dynamic position to avoid "jumps" when moving
- // between apps or activities.
- ? mAppCompatConfiguration.getVerticalMultiplierForReachability(tabletopMode)
- : mAppCompatConfiguration.getLetterboxVerticalPositionMultiplier(tabletopMode);
- }
-
boolean isLetterboxEducationEnabled() {
return mAppCompatConfiguration.getIsEducationEnabled();
}
- /**
- * @return {@value true} if the resulting app is letterboxed in a way defined as thin.
- */
- boolean isVerticalThinLetterboxed() {
- final int thinHeight = mAppCompatConfiguration.getThinLetterboxHeightPx();
- if (thinHeight < 0) {
- return false;
- }
- final Task task = mActivityRecord.getTask();
- if (task == null) {
- return false;
- }
- final int padding = Math.abs(
- task.getBounds().height() - mActivityRecord.getBounds().height()) / 2;
- return padding <= thinHeight;
- }
-
- /**
- * @return {@value true} if the resulting app is pillarboxed in a way defined as thin.
- */
- boolean isHorizontalThinLetterboxed() {
- final int thinWidth = mAppCompatConfiguration.getThinLetterboxWidthPx();
- if (thinWidth < 0) {
- return false;
- }
- final Task task = mActivityRecord.getTask();
- if (task == null) {
- return false;
- }
- final int padding = Math.abs(
- task.getBounds().width() - mActivityRecord.getBounds().width()) / 2;
- return padding <= thinWidth;
- }
-
-
- /**
- * @return {@value true} if the vertical reachability should be allowed in case of
- * thin letteboxing
- */
- boolean allowVerticalReachabilityForThinLetterbox() {
- if (!Flags.disableThinLetterboxingPolicy()) {
- return true;
- }
- // When the flag is enabled we allow vertical reachability only if the
- // app is not thin letterboxed vertically.
- return !isVerticalThinLetterboxed();
- }
-
- /**
- * @return {@value true} if the vertical reachability should be enabled in case of
- * thin letteboxing
- */
- boolean allowHorizontalReachabilityForThinLetterbox() {
- if (!Flags.disableThinLetterboxingPolicy()) {
- return true;
- }
- // When the flag is enabled we allow horizontal reachability only if the
- // app is not thin pillarboxed.
- return !isHorizontalThinLetterboxed();
- }
-
- boolean shouldOverrideMinAspectRatio() {
- return mActivityRecord.mAppCompatController.getAppCompatAspectRatioOverrides()
- .shouldOverrideMinAspectRatio();
- }
-
- @AppCompatConfiguration.LetterboxVerticalReachabilityPosition
- int getLetterboxPositionForVerticalReachability() {
- final boolean isInFullScreenTabletopMode = isDisplayFullScreenAndSeparatingHinge();
- return mAppCompatConfiguration.getLetterboxPositionForVerticalReachability(
- isInFullScreenTabletopMode);
- }
-
- @AppCompatConfiguration.LetterboxHorizontalReachabilityPosition
- int getLetterboxPositionForHorizontalReachability() {
- final boolean isInFullScreenBookMode = isFullScreenAndBookModeEnabled();
- return mAppCompatConfiguration.getLetterboxPositionForHorizontalReachability(
- isInFullScreenBookMode);
- }
-
- @VisibleForTesting
- void handleHorizontalDoubleTap(int x) {
- if (!isHorizontalReachabilityEnabled() || mActivityRecord.isInTransition()) {
- return;
- }
-
- if (mLetterbox.getInnerFrame().left <= x && mLetterbox.getInnerFrame().right >= x) {
- // Only react to clicks at the sides of the letterboxed app window.
- return;
- }
-
- boolean isInFullScreenBookMode = isDisplayFullScreenAndSeparatingHinge()
- && mAppCompatConfiguration.getIsAutomaticReachabilityInBookModeEnabled();
- int letterboxPositionForHorizontalReachability = mAppCompatConfiguration
- .getLetterboxPositionForHorizontalReachability(isInFullScreenBookMode);
- if (mLetterbox.getInnerFrame().left > x) {
- // Moving to the next stop on the left side of the app window: right > center > left.
- mAppCompatConfiguration.movePositionForHorizontalReachabilityToNextLeftStop(
- isInFullScreenBookMode);
- int changeToLog =
- letterboxPositionForHorizontalReachability
- == LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER
- ? LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_LEFT
- : LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__RIGHT_TO_CENTER;
- logLetterboxPositionChange(changeToLog);
- mDoubleTapEvent = true;
- } else if (mLetterbox.getInnerFrame().right < x) {
- // Moving to the next stop on the right side of the app window: left > center > right.
- mAppCompatConfiguration.movePositionForHorizontalReachabilityToNextRightStop(
- isInFullScreenBookMode);
- int changeToLog =
- letterboxPositionForHorizontalReachability
- == LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER
- ? LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_RIGHT
- : LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__LEFT_TO_CENTER;
- logLetterboxPositionChange(changeToLog);
- mDoubleTapEvent = true;
- }
- // TODO(197549949): Add animation for transition.
- mActivityRecord.recomputeConfiguration();
- }
-
- @VisibleForTesting
- void handleVerticalDoubleTap(int y) {
- if (!isVerticalReachabilityEnabled() || mActivityRecord.isInTransition()) {
- return;
- }
-
- if (mLetterbox.getInnerFrame().top <= y && mLetterbox.getInnerFrame().bottom >= y) {
- // Only react to clicks at the top and bottom of the letterboxed app window.
- return;
- }
- boolean isInFullScreenTabletopMode = isDisplayFullScreenAndSeparatingHinge();
- int letterboxPositionForVerticalReachability = mAppCompatConfiguration
- .getLetterboxPositionForVerticalReachability(isInFullScreenTabletopMode);
- if (mLetterbox.getInnerFrame().top > y) {
- // Moving to the next stop on the top side of the app window: bottom > center > top.
- mAppCompatConfiguration.movePositionForVerticalReachabilityToNextTopStop(
- isInFullScreenTabletopMode);
- int changeToLog =
- letterboxPositionForVerticalReachability
- == LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER
- ? LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_TOP
- : LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__BOTTOM_TO_CENTER;
- logLetterboxPositionChange(changeToLog);
- mDoubleTapEvent = true;
- } else if (mLetterbox.getInnerFrame().bottom < y) {
- // Moving to the next stop on the bottom side of the app window: top > center > bottom.
- mAppCompatConfiguration.movePositionForVerticalReachabilityToNextBottomStop(
- isInFullScreenTabletopMode);
- int changeToLog =
- letterboxPositionForVerticalReachability
- == LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER
- ? LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_BOTTOM
- : LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__TOP_TO_CENTER;
- logLetterboxPositionChange(changeToLog);
- mDoubleTapEvent = true;
- }
- // TODO(197549949): Add animation for transition.
- mActivityRecord.recomputeConfiguration();
- }
-
- /**
- * Whether horizontal reachability is enabled for an activity in the current configuration.
- *
- * <p>Conditions that needs to be met:
- * <ul>
- * <li>Windowing mode is fullscreen.
- * <li>Horizontal Reachability is enabled.
- * <li>First top opaque activity fills parent vertically, but not horizontally.
- * </ul>
- */
- private boolean isHorizontalReachabilityEnabled(Configuration parentConfiguration) {
- if (!allowHorizontalReachabilityForThinLetterbox()) {
- return false;
- }
- final Rect parentAppBoundsOverride = mActivityRecord.getParentAppBoundsOverride();
- final Rect parentAppBounds = parentAppBoundsOverride != null
- ? parentAppBoundsOverride : parentConfiguration.windowConfiguration.getAppBounds();
- // Use screen resolved bounds which uses resolved bounds or size compat bounds
- // as activity bounds can sometimes be empty
- final Rect opaqueActivityBounds = mActivityRecord.mAppCompatController
- .getTransparentPolicy().getFirstOpaqueActivity()
- .map(ActivityRecord::getScreenResolvedBounds)
- .orElse(mActivityRecord.getScreenResolvedBounds());
- return mAppCompatConfiguration.getIsHorizontalReachabilityEnabled()
- && parentConfiguration.windowConfiguration.getWindowingMode()
- == WINDOWING_MODE_FULLSCREEN
- // Check whether the activity fills the parent vertically.
- && parentAppBounds.height() <= opaqueActivityBounds.height()
- && parentAppBounds.width() > opaqueActivityBounds.width();
- }
-
- @VisibleForTesting
- boolean isHorizontalReachabilityEnabled() {
- return isHorizontalReachabilityEnabled(mActivityRecord.getParent().getConfiguration());
- }
-
- boolean isLetterboxDoubleTapEducationEnabled() {
- return isHorizontalReachabilityEnabled() || isVerticalReachabilityEnabled();
- }
-
- // TODO(b/346264992): Remove after AppCompatController refactoring
- private AppCompatOverrides getAppCompatOverrides() {
- return mActivityRecord.mAppCompatController.getAppCompatOverrides();
- }
-
- /**
- * Whether vertical reachability is enabled for an activity in the current configuration.
- *
- * <p>Conditions that needs to be met:
- * <ul>
- * <li>Windowing mode is fullscreen.
- * <li>Vertical Reachability is enabled.
- * <li>First top opaque activity fills parent horizontally but not vertically.
- * </ul>
- */
- private boolean isVerticalReachabilityEnabled(Configuration parentConfiguration) {
- if (!allowVerticalReachabilityForThinLetterbox()) {
- return false;
- }
- final Rect parentAppBoundsOverride = mActivityRecord.getParentAppBoundsOverride();
- final Rect parentAppBounds = parentAppBoundsOverride != null
- ? parentAppBoundsOverride : parentConfiguration.windowConfiguration.getAppBounds();
- // Use screen resolved bounds which uses resolved bounds or size compat bounds
- // as activity bounds can sometimes be empty.
- final Rect opaqueActivityBounds = mActivityRecord.mAppCompatController
- .getTransparentPolicy().getFirstOpaqueActivity()
- .map(ActivityRecord::getScreenResolvedBounds)
- .orElse(mActivityRecord.getScreenResolvedBounds());
- return mAppCompatConfiguration.getIsVerticalReachabilityEnabled()
- && parentConfiguration.windowConfiguration.getWindowingMode()
- == WINDOWING_MODE_FULLSCREEN
- // Check whether the activity fills the parent horizontally.
- && parentAppBounds.width() <= opaqueActivityBounds.width()
- && parentAppBounds.height() > opaqueActivityBounds.height();
- }
-
- @VisibleForTesting
- boolean isVerticalReachabilityEnabled() {
- return isVerticalReachabilityEnabled(mActivityRecord.getParent().getConfiguration());
- }
-
@VisibleForTesting
boolean shouldShowLetterboxUi(WindowState mainWindow) {
- if (getAppCompatOverrides().getAppCompatOrientationOverrides()
- .getIsRelaunchingAfterRequestedOrientationChanged()) {
+ if (mAppCompatOrientationOverrides.getIsRelaunchingAfterRequestedOrientationChanged()) {
return mLastShouldShowLetterboxUi;
}
@@ -664,8 +355,7 @@
// corners because we assume the specific layout would. This is the case when the layout
// of the translucent activity uses only a part of all the bounds because of the use of
// LayoutParams.WRAP_CONTENT.
- if (mActivityRecord.mAppCompatController.getTransparentPolicy().isRunning()
- && (cropBounds.width() != mainWindow.mRequestedWidth
+ if (mTransparentPolicy.isRunning() && (cropBounds.width() != mainWindow.mRequestedWidth
|| cropBounds.height() != mainWindow.mRequestedHeight)) {
return null;
}
@@ -808,7 +498,8 @@
return;
}
- pw.println(prefix + " letterboxReason=" + getLetterboxReasonString(mainWin));
+ pw.println(prefix + " letterboxReason="
+ + AppCompatUtils.getLetterboxReasonString(mActivityRecord, mainWin));
pw.println(prefix + " activityAspectRatio="
+ AppCompatUtils.computeAspectRatio(mActivityRecord.getBounds()));
@@ -818,8 +509,10 @@
if (!shouldShowLetterboxUi) {
return;
}
- pw.println(prefix + " isVerticalThinLetterboxed=" + isVerticalThinLetterboxed());
- pw.println(prefix + " isHorizontalThinLetterboxed=" + isHorizontalThinLetterboxed());
+ pw.println(prefix + " isVerticalThinLetterboxed="
+ + mAppCompatReachabilityOverrides.isVerticalThinLetterboxed());
+ pw.println(prefix + " isHorizontalThinLetterboxed="
+ + mAppCompatReachabilityOverrides.isHorizontalThinLetterboxed());
pw.println(prefix + " letterboxBackgroundColor=" + Integer.toHexString(
getLetterboxBackgroundColor().toArgb()));
pw.println(prefix + " letterboxBackgroundType="
@@ -836,14 +529,18 @@
pw.println(prefix + " letterboxBackgroundWallpaperBlurRadius="
+ getLetterboxWallpaperBlurRadiusPx());
}
-
+ final AppCompatReachabilityOverrides reachabilityOverrides = mActivityRecord
+ .mAppCompatController.getAppCompatReachabilityOverrides();
pw.println(prefix + " isHorizontalReachabilityEnabled="
- + isHorizontalReachabilityEnabled());
- pw.println(prefix + " isVerticalReachabilityEnabled=" + isVerticalReachabilityEnabled());
+ + reachabilityOverrides.isHorizontalReachabilityEnabled());
+ pw.println(prefix + " isVerticalReachabilityEnabled="
+ + reachabilityOverrides.isVerticalReachabilityEnabled());
pw.println(prefix + " letterboxHorizontalPositionMultiplier="
- + getHorizontalPositionMultiplier(mActivityRecord.getParent().getConfiguration()));
+ + mAppCompatReachabilityOverrides.getHorizontalPositionMultiplier(mActivityRecord
+ .getParent().getConfiguration()));
pw.println(prefix + " letterboxVerticalPositionMultiplier="
- + getVerticalPositionMultiplier(mActivityRecord.getParent().getConfiguration()));
+ + mAppCompatReachabilityOverrides.getVerticalPositionMultiplier(mActivityRecord
+ .getParent().getConfiguration()));
pw.println(prefix + " letterboxPositionForHorizontalReachability="
+ AppCompatConfiguration.letterboxHorizontalReachabilityPositionToString(
mAppCompatConfiguration.getLetterboxPositionForHorizontalReachability(false)));
@@ -861,86 +558,6 @@
.getIsDisplayAspectRatioEnabledForFixedOrientationLetterbox());
}
- /**
- * Returns a string representing the reason for letterboxing. This method assumes the activity
- * is letterboxed.
- */
- private String getLetterboxReasonString(WindowState mainWin) {
- if (mActivityRecord.inSizeCompatMode()) {
- return "SIZE_COMPAT_MODE";
- }
- if (mActivityRecord.mAppCompatController.getAppCompatAspectRatioPolicy()
- .isLetterboxedForFixedOrientationAndAspectRatio()) {
- return "FIXED_ORIENTATION";
- }
- if (mainWin.isLetterboxedForDisplayCutout()) {
- return "DISPLAY_CUTOUT";
- }
- if (mActivityRecord.mAppCompatController.getAppCompatAspectRatioPolicy()
- .isLetterboxedForAspectRatioOnly()) {
- return "ASPECT_RATIO";
- }
- return "UNKNOWN_REASON";
- }
-
- private int letterboxHorizontalReachabilityPositionToLetterboxPosition(
- @AppCompatConfiguration.LetterboxHorizontalReachabilityPosition int position) {
- switch (position) {
- case LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT:
- return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__LEFT;
- case LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER:
- return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__CENTER;
- case LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT:
- return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__RIGHT;
- default:
- throw new AssertionError(
- "Unexpected letterbox horizontal reachability position type: "
- + position);
- }
- }
-
- private int letterboxVerticalReachabilityPositionToLetterboxPosition(
- @AppCompatConfiguration.LetterboxVerticalReachabilityPosition int position) {
- switch (position) {
- case LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP:
- return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__TOP;
- case LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER:
- return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__CENTER;
- case LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM:
- return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__BOTTOM;
- default:
- throw new AssertionError(
- "Unexpected letterbox vertical reachability position type: "
- + position);
- }
- }
-
- int getLetterboxPositionForLogging() {
- int positionToLog = APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__UNKNOWN_POSITION;
- if (isHorizontalReachabilityEnabled()) {
- int letterboxPositionForHorizontalReachability = mAppCompatConfiguration
- .getLetterboxPositionForHorizontalReachability(
- isDisplayFullScreenAndInPosture(/* isTabletop */ false));
- positionToLog = letterboxHorizontalReachabilityPositionToLetterboxPosition(
- letterboxPositionForHorizontalReachability);
- } else if (isVerticalReachabilityEnabled()) {
- int letterboxPositionForVerticalReachability = mAppCompatConfiguration
- .getLetterboxPositionForVerticalReachability(
- isDisplayFullScreenAndInPosture(/* isTabletop */ true));
- positionToLog = letterboxVerticalReachabilityPositionToLetterboxPosition(
- letterboxPositionForVerticalReachability);
- }
- return positionToLog;
- }
-
- /**
- * Logs letterbox position changes via {@link ActivityMetricsLogger#logLetterboxPositionChange}.
- */
- private void logLetterboxPositionChange(int letterboxPositionChange) {
- mActivityRecord.mTaskSupervisor.getActivityMetricsLogger()
- .logLetterboxPositionChange(mActivityRecord, letterboxPositionChange);
- }
-
@Nullable
LetterboxDetails getLetterboxDetails() {
final WindowState w = mActivityRecord.findMainWindow();
diff --git a/services/core/java/com/android/server/wm/SnapshotController.java b/services/core/java/com/android/server/wm/SnapshotController.java
index cb388ef..99e1e8b 100644
--- a/services/core/java/com/android/server/wm/SnapshotController.java
+++ b/services/core/java/com/android/server/wm/SnapshotController.java
@@ -186,11 +186,11 @@
}
mActivitySnapshotController.handleTransitionFinish(windows);
mActivitySnapshotController.endSnapshotProcess();
- // Remove task snapshot if it is visible at the end of transition.
+ // Remove task snapshot if it is visible at the end of transition, except for PiP.
for (int i = changeInfos.size() - 1; i >= 0; --i) {
final WindowContainer wc = changeInfos.get(i).mContainer;
final Task task = wc.asTask();
- if (task != null && wc.isVisibleRequested()) {
+ if (task != null && wc.isVisibleRequested() && !task.inPinnedWindowingMode()) {
final TaskSnapshot snapshot = mTaskSnapshotController.getSnapshot(task.mTaskId,
task.mUserId, false /* restoreFromDisk */, false /* isLowResolution */);
if (snapshot != null) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 1c9aaf9..d3df5fd 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -130,9 +130,7 @@
import android.app.ActivityManager.TaskDescription;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
-import android.app.AppCompatTaskInfo;
import android.app.AppGlobals;
-import android.app.CameraCompatTaskInfo;
import android.app.IActivityController;
import android.app.PictureInPictureParams;
import android.app.TaskInfo;
@@ -3380,29 +3378,6 @@
? top.getLastParentBeforePip().mTaskId : INVALID_TASK_ID;
info.shouldDockBigOverlays = top != null && top.shouldDockBigOverlays;
info.mTopActivityLocusId = top != null ? top.getLocusId() : null;
-
- final boolean isTopActivityResumed = top != null
- && top.getOrganizedTask() == this && top.isState(RESUMED);
- final boolean isTopActivityVisible = top != null
- && top.getOrganizedTask() == this && top.isVisible();
- final AppCompatTaskInfo appCompatTaskInfo = info.appCompatTaskInfo;
- // Whether the direct top activity is in size compat mode
- appCompatTaskInfo.topActivityInSizeCompat = isTopActivityVisible && top.inSizeCompatMode();
- if (appCompatTaskInfo.topActivityInSizeCompat
- && mWmService.mAppCompatConfiguration.isTranslucentLetterboxingEnabled()) {
- // We hide the restart button in case of transparent activities.
- appCompatTaskInfo.topActivityInSizeCompat = top.fillsParent();
- }
- // Whether the direct top activity is eligible for letterbox education.
- appCompatTaskInfo.topActivityEligibleForLetterboxEducation = isTopActivityResumed
- && top.isEligibleForLetterboxEducation();
- appCompatTaskInfo.isLetterboxEducationEnabled = top != null
- && top.mLetterboxUiController.isLetterboxEducationEnabled();
- // Whether the direct top activity requested showing camera compat control.
- appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState = isTopActivityResumed
- ? top.getCameraCompatControlState()
- : CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
-
final Task parentTask = getParent() != null ? getParent().asTask() : null;
info.parentTaskId = parentTask != null && parentTask.mCreatedByOrganizer
? parentTask.mTaskId
@@ -3414,57 +3389,7 @@
info.isTopActivityTransparent = top != null && !top.fillsParent();
info.isTopActivityStyleFloating = top != null && top.isStyleFloating();
info.lastNonFullscreenBounds = topTask.mLastNonFullscreenBounds;
- appCompatTaskInfo.topActivityLetterboxVerticalPosition = TaskInfo.PROPERTY_VALUE_UNSET;
- appCompatTaskInfo.topActivityLetterboxHorizontalPosition = TaskInfo.PROPERTY_VALUE_UNSET;
- appCompatTaskInfo.topActivityLetterboxWidth = TaskInfo.PROPERTY_VALUE_UNSET;
- appCompatTaskInfo.topActivityLetterboxHeight = TaskInfo.PROPERTY_VALUE_UNSET;
- appCompatTaskInfo.isUserFullscreenOverrideEnabled = top != null
- && top.mAppCompatController.getAppCompatAspectRatioOverrides()
- .shouldApplyUserFullscreenOverride();
- appCompatTaskInfo.isSystemFullscreenOverrideEnabled = top != null
- && top.mAppCompatController.getAppCompatAspectRatioOverrides()
- .isSystemOverrideToFullscreenEnabled();
- appCompatTaskInfo.isFromLetterboxDoubleTap = top != null
- && top.mLetterboxUiController.isFromDoubleTap();
- if (top != null) {
- appCompatTaskInfo.topActivityLetterboxWidth = top.getBounds().width();
- appCompatTaskInfo.topActivityLetterboxHeight = top.getBounds().height();
- }
- // We need to consider if letterboxed or pillarboxed
- // TODO(b/336807329) Encapsulate reachability logic
- appCompatTaskInfo.isLetterboxDoubleTapEnabled = top != null
- && top.mLetterboxUiController.isLetterboxDoubleTapEducationEnabled();
- if (appCompatTaskInfo.isLetterboxDoubleTapEnabled) {
- if (appCompatTaskInfo.isTopActivityPillarboxed()) {
- if (top.mLetterboxUiController.allowHorizontalReachabilityForThinLetterbox()) {
- // Pillarboxed
- appCompatTaskInfo.topActivityLetterboxHorizontalPosition =
- top.mLetterboxUiController
- .getLetterboxPositionForHorizontalReachability();
- } else {
- appCompatTaskInfo.isLetterboxDoubleTapEnabled = false;
- }
- } else {
- if (top.mLetterboxUiController.allowVerticalReachabilityForThinLetterbox()) {
- // Letterboxed
- appCompatTaskInfo.topActivityLetterboxVerticalPosition =
- top.mLetterboxUiController
- .getLetterboxPositionForVerticalReachability();
- } else {
- appCompatTaskInfo.isLetterboxDoubleTapEnabled = false;
- }
- }
- }
- appCompatTaskInfo.topActivityEligibleForUserAspectRatioButton = top != null
- && !appCompatTaskInfo.topActivityInSizeCompat
- && top.mAppCompatController.getAppCompatAspectRatioOverrides()
- .shouldEnableUserAspectRatioSettings()
- && !info.isTopActivityTransparent;
- appCompatTaskInfo.topActivityBoundsLetterboxed = top != null && top.areBoundsLetterboxed();
- appCompatTaskInfo.cameraCompatTaskInfo.freeformCameraCompatMode = top == null
- ? CameraCompatTaskInfo.CAMERA_COMPAT_FREEFORM_NONE
- : top.mAppCompatController.getAppCompatCameraOverrides()
- .getFreeformCameraCompatMode();
+ AppCompatUtils.fillAppCompatTaskInfo(this, info, top);
}
/**
@@ -3513,6 +3438,9 @@
if (task.effectiveUid != baseActivityUid) {
info.baseActivity = new ComponentName("", "");
}
+
+ info.capturedLink = null;
+ info.capturedLinkTimestamp = 0;
}
@Nullable PictureInPictureParams getPictureInPictureParams() {
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 6e36d427..2c5beda 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
-import static android.app.CameraCompatTaskInfo.cameraCompatControlStateToString;
import static android.window.StartingWindowRemovalInfo.DEFER_MODE_NONE;
import static android.window.StartingWindowRemovalInfo.DEFER_MODE_NORMAL;
import static android.window.StartingWindowRemovalInfo.DEFER_MODE_ROTATION;
@@ -1128,35 +1127,6 @@
}
}
- @Override
- public void updateCameraCompatControlState(WindowContainerToken token, int state) {
- enforceTaskPermission("updateCameraCompatControlState()");
- final long origId = Binder.clearCallingIdentity();
- try {
- synchronized (mGlobalLock) {
- final WindowContainer wc = WindowContainer.fromBinder(token.asBinder());
- if (wc == null) {
- Slog.w(TAG, "Could not resolve window from token");
- return;
- }
- final Task task = wc.asTask();
- if (task == null) {
- Slog.w(TAG, "Could not resolve task from token");
- return;
- }
- ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
- "Update camera compat control state to %s for taskId=%d",
- cameraCompatControlStateToString(state), task.mTaskId);
- final ActivityRecord activity = task.getTopNonFinishingActivity();
- if (activity != null) {
- activity.updateCameraCompatStateFromUser(state);
- }
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
-
public boolean handleInterceptBackPressedOnTaskRoot(Task task) {
if (!shouldInterceptBackPressedOnRootTask(task)) {
return false;
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index af3ed28..5698750 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -18,6 +18,7 @@
import static android.app.ActivityOptions.ANIM_CUSTOM;
import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS;
+import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
@@ -1763,7 +1764,7 @@
// Check whether the participants were animated from back navigation.
mController.mAtm.mBackNavigationController.onTransactionReady(this, mTargets,
- transaction);
+ transaction, mFinishTransaction);
final TransitionInfo info = calculateTransitionInfo(mType, mFlags, mTargets, transaction);
info.setDebugId(mSyncId);
mController.assignTrack(this, info);
@@ -1936,8 +1937,7 @@
for (int i = changes.size() - 1; i >= 0; --i) {
final WindowContainer<?> container = mTargets.get(i).mContainer;
if (container.asActivityRecord() != null
- || (container.asTask() != null
- && mOverrideOptions.getOverrideTaskTransition())) {
+ || shouldApplyAnimOptionsToTask(container.asTask())) {
changes.get(i).setAnimationOptions(mOverrideOptions);
// TODO(b/295805497): Extract mBackgroundColor from AnimationOptions.
changes.get(i).setBackgroundColor(mOverrideOptions.getBackgroundColor());
@@ -1951,6 +1951,16 @@
updateActivityTargetForCrossProfileAnimation(info);
}
+ private boolean shouldApplyAnimOptionsToTask(@Nullable Task task) {
+ if (task == null || mOverrideOptions == null) {
+ return false;
+ }
+ final int animType = mOverrideOptions.getType();
+ // Only apply AnimationOptions to Task if it is specified in #getOverrideTaskTransition
+ // or it's ANIM_SCENE_TRANSITION.
+ return animType == ANIM_SCENE_TRANSITION || mOverrideOptions.getOverrideTaskTransition();
+ }
+
private boolean shouldApplyAnimOptionsToEmbeddedTf(@Nullable TaskFragment taskFragment) {
if (taskFragment == null || !taskFragment.isEmbedded()) {
return false;
@@ -2192,6 +2202,11 @@
&& !wallpaperIsOwnTarget(wallpaper)) {
wallpaper.setVisibleRequested(false);
}
+ if (showWallpaper && wallpaper.isVisibleRequested()) {
+ for (int j = wallpaper.mChildren.size() - 1; j >= 0; --j) {
+ wallpaper.mChildren.get(j).mWinAnimator.prepareSurfaceLocked(t);
+ }
+ }
}
}
}
@@ -2377,6 +2392,7 @@
sb.append(" id=" + mSyncId);
sb.append(" type=" + transitTypeToString(mType));
sb.append(" flags=0x" + Integer.toHexString(mFlags));
+ sb.append(" overrideAnimOptions=" + mOverrideOptions);
sb.append('}');
return sb.toString();
}
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 2652670..6ea1f3a 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -1064,13 +1064,17 @@
/**
* Mirrors the visible wallpaper if it's available.
+ * <p>
+ * We mirror at the WallpaperWindowToken level because scale and translation is applied at
+ * the WindowState level and mirroring the WindowState's SurfaceControl will remove any local
+ * scale and translation.
*
* @return A SurfaceControl for the parent of the mirrored wallpaper.
*/
SurfaceControl mirrorWallpaperSurface() {
final WindowState wallpaperWindowState = getTopVisibleWallpaper();
return wallpaperWindowState != null
- ? SurfaceControl.mirrorSurface(wallpaperWindowState.getSurfaceControl())
+ ? SurfaceControl.mirrorSurface(wallpaperWindowState.mToken.getSurfaceControl())
: null;
}
diff --git a/services/core/java/com/android/server/wm/WindowAnimationSpec.java b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
index 2c58c61..34b9913 100644
--- a/services/core/java/com/android/server/wm/WindowAnimationSpec.java
+++ b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
@@ -97,10 +97,10 @@
/**
* @return If a window animation has outsets applied to it.
- * @see Animation#getExtensionEdges()
+ * @see Animation#hasExtension()
*/
public boolean hasExtension() {
- return mAnimation.getExtensionEdges() != 0;
+ return mAnimation.hasExtension();
}
@Override
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 48a5050..a574845 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -690,15 +690,10 @@
* <p>Only {@link com.android.server.inputmethod.InputMethodManagerService} is the expected and
* tested caller of this method.</p>
*
- * @param imeToken token to track the active input method. Corresponding IME windows can be
- * identified by checking {@link android.view.WindowManager.LayoutParams#token}.
- * Note that there is no guarantee that the corresponding window is already
- * created
* @param imeTargetWindowToken token to identify the target window that the IME is associated
* with
*/
- public abstract void updateInputMethodTargetWindow(@NonNull IBinder imeToken,
- @NonNull IBinder imeTargetWindowToken);
+ public abstract void updateInputMethodTargetWindow(@NonNull IBinder imeTargetWindowToken);
/**
* Returns true when the hardware keyboard is available.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 13453a6..cf92f1b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1897,7 +1897,8 @@
displayContent.computeImeTarget(true /* updateImeTarget */);
if (win.isImeOverlayLayeringTarget()) {
dispatchImeTargetOverlayVisibilityChanged(client.asBinder(), win.mAttrs.type,
- win.isVisibleRequestedOrAdding(), false /* removed */);
+ win.isVisibleRequestedOrAdding(), false /* removed */,
+ displayContent.getDisplayId());
}
}
@@ -2661,13 +2662,13 @@
final boolean winVisibleChanged = win.isVisible() != wasVisible;
if (win.isImeOverlayLayeringTarget() && winVisibleChanged) {
dispatchImeTargetOverlayVisibilityChanged(client.asBinder(), win.mAttrs.type,
- win.isVisible(), false /* removed */);
+ win.isVisible(), false /* removed */, win.getDisplayId());
}
// Notify listeners about IME input target window visibility change.
final boolean isImeInputTarget = win.getDisplayContent().getImeInputTarget() == win;
if (isImeInputTarget && winVisibleChanged) {
dispatchImeInputTargetVisibilityChanged(win.mClient.asBinder(),
- win.isVisible() /* visible */, false /* removed */);
+ win.isVisible() /* visible */, false /* removed */, win.getDisplayId());
}
if (outRelayoutResult != null) {
@@ -3515,27 +3516,29 @@
void dispatchImeTargetOverlayVisibilityChanged(@NonNull IBinder token,
@WindowManager.LayoutParams.WindowType int windowType, boolean visible,
- boolean removed) {
+ boolean removed, int displayId) {
if (mImeTargetChangeListener != null) {
if (DEBUG_INPUT_METHOD) {
Slog.d(TAG, "onImeTargetOverlayVisibilityChanged, win=" + mWindowMap.get(token)
+ ", type=" + ViewDebug.intToString(WindowManager.LayoutParams.class,
- "type", windowType) + "visible=" + visible + ", removed=" + removed);
+ "type", windowType) + "visible=" + visible + ", removed=" + removed
+ + ", displayId=" + displayId);
}
mH.post(() -> mImeTargetChangeListener.onImeTargetOverlayVisibilityChanged(token,
- windowType, visible, removed));
+ windowType, visible, removed, displayId));
}
}
void dispatchImeInputTargetVisibilityChanged(@NonNull IBinder token, boolean visible,
- boolean removed) {
+ boolean removed, int displayId) {
if (mImeTargetChangeListener != null) {
if (DEBUG_INPUT_METHOD) {
Slog.d(TAG, "onImeInputTargetVisibilityChanged, win=" + mWindowMap.get(token)
- + "visible=" + visible + ", removed=" + removed);
+ + "visible=" + visible + ", removed=" + removed
+ + ", displayId" + displayId);
}
mH.post(() -> mImeTargetChangeListener.onImeInputTargetVisibilityChanged(token,
- visible, removed));
+ visible, removed, displayId));
}
}
@@ -8094,11 +8097,10 @@
}
@Override
- public void updateInputMethodTargetWindow(@NonNull IBinder imeToken,
- @NonNull IBinder imeTargetWindowToken) {
+ public void updateInputMethodTargetWindow(@NonNull IBinder imeTargetWindowToken) {
// TODO (b/34628091): Use this method to address the window animation issue.
if (DEBUG_INPUT_METHOD) {
- Slog.w(TAG_WM, "updateInputMethodTargetWindow: imeToken=" + imeToken
+ Slog.w(TAG_WM, "updateInputMethodTargetWindow:"
+ " imeTargetWindowToken=" + imeTargetWindowToken);
}
synchronized (mGlobalLock) {
@@ -9036,7 +9038,8 @@
// Otherwise, handle the touch-outside event directly.
final WindowState w = t.getWindowState();
final ActivityRecord activity = w != null ? w.getActivityRecord() : null;
- if (activity != null && activity.isEmbedded()
+ if (mFocusedInputTarget != t && mFocusedInputTarget != null
+ && activity != null && activity.isEmbedded()
&& activity.getTaskFragment().getAdjacentTaskFragment() != null) {
mPointerDownOutsideFocusRunnable = () -> handlePointerDownOutsideFocus(t);
mH.postDelayed(mPointerDownOutsideFocusRunnable, POINTER_DOWN_OUTSIDE_FOCUS_TIMEOUT_MS);
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index 51d5bc0..092a751 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -284,30 +284,28 @@
private int runDisplayDensity(PrintWriter pw) throws RemoteException {
String densityStr = getNextArg();
- String option = getNextOption();
String arg = getNextArg();
int density;
int displayId = Display.DEFAULT_DISPLAY;
- if ("-d".equals(option) && arg != null) {
+ if ("-d".equals(densityStr) && arg != null) {
try {
displayId = Integer.parseInt(arg);
} catch (NumberFormatException e) {
getErrPrintWriter().println("Error: bad number " + e);
}
- } else if ("-u".equals(option) && arg != null) {
+ densityStr = getNextArg();
+ } else if ("-u".equals(densityStr) && arg != null) {
displayId = mInterface.getDisplayIdByUniqueId(arg);
if (displayId == Display.INVALID_DISPLAY) {
getErrPrintWriter().println("Error: the uniqueId is invalid ");
return -1;
}
+ densityStr = getNextArg();
}
if (densityStr == null) {
printInitialDisplayDensity(pw, displayId);
return 0;
- } else if ("-d".equals(densityStr)) {
- printInitialDisplayDensity(pw, displayId);
- return 0;
} else if ("reset".equals(densityStr)) {
density = -1;
} else {
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index bc32b91..0093e9d 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -390,7 +390,10 @@
private static boolean hasActivityLaunch(@NonNull WindowContainerTransaction wct) {
for (int i = 0; i < wct.getHierarchyOps().size(); ++i) {
- if (wct.getHierarchyOps().get(i).getType() == HIERARCHY_OP_TYPE_LAUNCH_TASK) {
+ final WindowContainerTransaction.HierarchyOp op = wct.getHierarchyOps().get(i);
+ if (op.getType() == HIERARCHY_OP_TYPE_LAUNCH_TASK
+ || (op.getType() == HIERARCHY_OP_TYPE_PENDING_INTENT
+ && op.getPendingIntent().isActivity())) {
return true;
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 153d41b..e646752 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2359,11 +2359,11 @@
}
super.removeImmediately();
+ final DisplayContent dc = getDisplayContent();
if (isImeOverlayLayeringTarget()) {
mWmService.dispatchImeTargetOverlayVisibilityChanged(mClient.asBinder(), mAttrs.type,
- false /* visible */, true /* removed */);
+ false /* visible */, true /* removed */, dc.getDisplayId());
}
- final DisplayContent dc = getDisplayContent();
if (isImeLayeringTarget()) {
// Remove the attached IME screenshot surface.
dc.removeImeSurfaceByTarget(this);
@@ -2374,7 +2374,7 @@
}
if (dc.getImeInputTarget() == this && !inRelaunchingActivity()) {
mWmService.dispatchImeInputTargetVisibilityChanged(mClient.asBinder(),
- false /* visible */, true /* removed */);
+ false /* visible */, true /* removed */, dc.getDisplayId());
dc.updateImeInputAndControlTarget(null);
}
@@ -4415,6 +4415,11 @@
for (int i = mChildren.size() - 1; i >= 0; i--) {
committed |= mChildren.get(i).commitFinishDrawing(t);
}
+ // In case commitFinishDrawingLocked starts a window level animation, make sure the surface
+ // operation (reparent to leash) is synced with the visibility by transition.
+ if (getAnimationLeash() != null) {
+ t.merge(getSyncTransaction());
+ }
return committed;
}
@@ -5028,7 +5033,9 @@
new WindowAnimationSpec(anim, position, false /* canSkipFirstFrame */,
0 /* windowCornerRadius */),
mWmService.mSurfaceAnimationRunner);
- startAnimation(getPendingTransaction(), adapter);
+ final Transaction t = mActivityRecord != null
+ ? getSyncTransaction() : getPendingTransaction();
+ startAnimation(t, adapter);
commitPendingTransaction();
}
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 9fa1a53..f1e94de 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -79,6 +79,7 @@
"com_android_server_wm_TaskFpsCallbackController.cpp",
"onload.cpp",
":lib_cachedAppOptimizer_native",
+ ":lib_freezer_native",
":lib_gameManagerService_native",
":lib_oomConnection_native",
":lib_anrTimer_native",
@@ -241,6 +242,13 @@
}
filegroup {
+ name: "lib_freezer_native",
+ srcs: [
+ "com_android_server_am_Freezer.cpp",
+ ],
+}
+
+filegroup {
name: "lib_gameManagerService_native",
srcs: [
"com_android_server_app_GameManagerService.cpp",
diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS
index 1667e27..b622751 100644
--- a/services/core/jni/OWNERS
+++ b/services/core/jni/OWNERS
@@ -27,7 +27,8 @@
per-file com_android_server_security_* = file:/core/java/android/security/OWNERS
per-file com_android_server_tv_* = file:/media/java/android/media/tv/OWNERS
per-file com_android_server_vibrator_* = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file com_android_server_am_CachedAppOptimizer.cpp = timmurray@google.com, edgararriaga@google.com, dualli@google.com, carmenjackson@google.com, philipcuadra@google.com
+per-file com_android_server_am_CachedAppOptimizer.cpp = file:/PERFORMANCE_OWNERS
+per-file com_android_server_am_Freezer.cpp = file:/PERFORMANCE_OWNERS
per-file com_android_server_companion_virtual_InputController.cpp = file:/services/companion/java/com/android/server/companion/virtual/OWNERS
# Memory
diff --git a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
index 95e7b19..a91fd08 100644
--- a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
+++ b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
@@ -24,7 +24,6 @@
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
#include <android_runtime/AndroidRuntime.h>
-#include <binder/IPCThreadState.h>
#include <cutils/compiler.h>
#include <dirent.h>
#include <jni.h>
@@ -34,7 +33,6 @@
#include <meminfo/procmeminfo.h>
#include <meminfo/sysmeminfo.h>
#include <nativehelper/JNIHelp.h>
-#include <processgroup/processgroup.h>
#include <stddef.h>
#include <stdio.h>
#include <sys/mman.h>
@@ -63,10 +61,6 @@
using VmaToAdviseFunc = std::function<int(const Vma&)>;
using android::base::unique_fd;
-#define SYNC_RECEIVED_WHILE_FROZEN (1)
-#define ASYNC_RECEIVED_WHILE_FROZEN (2)
-#define TXNS_PENDING_WHILE_FROZEN (4)
-
#define MAX_RW_COUNT (INT_MAX & kPageMask)
// Defines the maximum amount of VMAs we can send per process_madvise syscall.
@@ -527,58 +521,6 @@
compactProcessOrFallback(pid, compactionFlags);
}
-static jint com_android_server_am_CachedAppOptimizer_freezeBinder(JNIEnv* env, jobject clazz,
- jint pid, jboolean freeze,
- jint timeout_ms) {
- jint retVal = IPCThreadState::freeze(pid, freeze, timeout_ms);
- if (retVal != 0 && retVal != -EAGAIN) {
- jniThrowException(env, "java/lang/RuntimeException", "Unable to freeze/unfreeze binder");
- }
-
- return retVal;
-}
-
-static jint com_android_server_am_CachedAppOptimizer_getBinderFreezeInfo(JNIEnv *env,
- jobject clazz, jint pid) {
- uint32_t syncReceived = 0, asyncReceived = 0;
-
- int error = IPCThreadState::getProcessFreezeInfo(pid, &syncReceived, &asyncReceived);
-
- if (error < 0) {
- jniThrowException(env, "java/lang/RuntimeException", strerror(error));
- }
-
- jint retVal = 0;
-
- // bit 0 of sync_recv goes to bit 0 of retVal
- retVal |= syncReceived & SYNC_RECEIVED_WHILE_FROZEN;
- // bit 0 of async_recv goes to bit 1 of retVal
- retVal |= (asyncReceived << 1) & ASYNC_RECEIVED_WHILE_FROZEN;
- // bit 1 of sync_recv goes to bit 2 of retVal
- retVal |= (syncReceived << 1) & TXNS_PENDING_WHILE_FROZEN;
-
- return retVal;
-}
-
-static jstring com_android_server_am_CachedAppOptimizer_getFreezerCheckPath(JNIEnv* env,
- jobject clazz) {
- std::string path;
-
- if (!getAttributePathForTask("FreezerState", getpid(), &path)) {
- path = "";
- }
-
- return env->NewStringUTF(path.c_str());
-}
-
-static jboolean com_android_server_am_CachedAppOptimizer_isFreezerProfileValid(JNIEnv* env) {
- uid_t uid = getuid();
- pid_t pid = getpid();
-
- return isProfileValidForProcess("Frozen", uid, pid) &&
- isProfileValidForProcess("Unfrozen", uid, pid);
-}
-
static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"cancelCompaction", "()V",
@@ -592,13 +534,7 @@
(void*)com_android_server_am_CachedAppOptimizer_getMemoryFreedCompaction},
{"compactSystem", "()V", (void*)com_android_server_am_CachedAppOptimizer_compactSystem},
{"compactProcess", "(II)V", (void*)com_android_server_am_CachedAppOptimizer_compactProcess},
- {"freezeBinder", "(IZI)I", (void*)com_android_server_am_CachedAppOptimizer_freezeBinder},
- {"getBinderFreezeInfo", "(I)I",
- (void*)com_android_server_am_CachedAppOptimizer_getBinderFreezeInfo},
- {"getFreezerCheckPath", "()Ljava/lang/String;",
- (void*)com_android_server_am_CachedAppOptimizer_getFreezerCheckPath},
- {"isFreezerProfileValid", "()Z",
- (void*)com_android_server_am_CachedAppOptimizer_isFreezerProfileValid}};
+};
int register_android_server_am_CachedAppOptimizer(JNIEnv* env)
{
diff --git a/services/core/jni/com_android_server_am_Freezer.cpp b/services/core/jni/com_android_server_am_Freezer.cpp
new file mode 100644
index 0000000..8148728
--- /dev/null
+++ b/services/core/jni/com_android_server_am_Freezer.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Freezer"
+//#define LOG_NDEBUG 0
+#define ATRACE_TAG ATRACE_TAG_ACTIVITY_MANAGER
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+#include <binder/IPCThreadState.h>
+#include <nativehelper/JNIHelp.h>
+#include <processgroup/processgroup.h>
+
+namespace android {
+namespace {
+
+// Binder status bit flags.
+static const int SYNC_RECEIVED_WHILE_FROZEN = 1;
+static const int ASYNC_RECEIVED_WHILE_FROZEN = 2;
+static const int TXNS_PENDING_WHILE_FROZEN = 4;
+
+jint freezeBinder(JNIEnv* env, jobject, jint pid, jboolean freeze, jint timeout_ms) {
+ jint retVal = IPCThreadState::freeze(pid, freeze, timeout_ms);
+ if (retVal != 0 && retVal != -EAGAIN) {
+ jniThrowException(env, "java/lang/RuntimeException", "Unable to freeze/unfreeze binder");
+ }
+
+ return retVal;
+}
+
+jint getBinderFreezeInfo(JNIEnv *env, jobject, jint pid) {
+ uint32_t syncReceived = 0, asyncReceived = 0;
+
+ int error = IPCThreadState::getProcessFreezeInfo(pid, &syncReceived, &asyncReceived);
+
+ if (error < 0) {
+ jniThrowException(env, "java/lang/RuntimeException", strerror(error));
+ }
+
+ jint retVal = 0;
+
+ // bit 0 of sync_recv goes to bit 0 of retVal
+ retVal |= syncReceived & SYNC_RECEIVED_WHILE_FROZEN;
+ // bit 0 of async_recv goes to bit 1 of retVal
+ retVal |= (asyncReceived << 1) & ASYNC_RECEIVED_WHILE_FROZEN;
+ // bit 1 of sync_recv goes to bit 2 of retVal
+ retVal |= (syncReceived << 1) & TXNS_PENDING_WHILE_FROZEN;
+
+ return retVal;
+}
+
+bool isFreezerSupported(JNIEnv *env, jclass) {
+ std::string path;
+ if (!getAttributePathForTask("FreezerState", getpid(), &path)) {
+ ALOGI("No attribute for FreezerState");
+ return false;
+ }
+ base::unique_fd fid(open(path.c_str(), O_RDONLY));
+ if (fid < 0) {
+ ALOGI("Cannot open freezer path \"%s\": %s", path.c_str(), strerror(errno));
+ return false;
+ }
+
+ char state;
+ if (::read(fid, &state, 1) != 1) {
+ ALOGI("Failed to read freezer state: %s", strerror(errno));
+ return false;
+ }
+ if (state != '1' && state != '0') {
+ ALOGE("Unexpected value in cgroup.freeze: %d", state);
+ return false;
+ }
+
+ uid_t uid = getuid();
+ pid_t pid = getpid();
+
+ uint32_t syncReceived = 0, asyncReceived = 0;
+ int error = IPCThreadState::getProcessFreezeInfo(pid, &syncReceived, &asyncReceived);
+ if (error < 0) {
+ ALOGE("Unable to read freezer info: %s", strerror(errno));
+ return false;
+ }
+
+ if (!isProfileValidForProcess("Frozen", uid, pid)
+ || !isProfileValidForProcess("Unfrozen", uid, pid)) {
+ ALOGE("Missing freezer profiles");
+ return false;
+ }
+
+ return true;
+}
+
+static const JNINativeMethod sMethods[] = {
+ {"nativeIsFreezerSupported", "()Z", (void*) isFreezerSupported },
+ {"nativeFreezeBinder", "(IZI)I", (void*) freezeBinder },
+ {"nativeGetBinderFreezeInfo", "(I)I", (void*) getBinderFreezeInfo },
+};
+
+} // end of anonymous namespace
+
+int register_android_server_am_Freezer(JNIEnv* env)
+{
+ char const *className = "com/android/server/am/Freezer";
+ return jniRegisterNativeMethods(env, className, sMethods, NELEM(sMethods));
+}
+
+} // end of namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 314ff9d..3c55d18 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -54,6 +54,7 @@
int register_android_hardware_display_DisplayViewport(JNIEnv* env);
int register_android_server_am_OomConnection(JNIEnv* env);
int register_android_server_am_CachedAppOptimizer(JNIEnv* env);
+int register_android_server_am_Freezer(JNIEnv* env);
int register_android_server_am_LowMemDetector(JNIEnv* env);
int register_android_server_utils_AnrTimer(JNIEnv *env);
int register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(JNIEnv* env);
@@ -118,6 +119,7 @@
register_android_hardware_display_DisplayViewport(env);
register_android_server_am_OomConnection(env);
register_android_server_am_CachedAppOptimizer(env);
+ register_android_server_am_Freezer(env);
register_android_server_am_LowMemDetector(env);
register_android_server_utils_AnrTimer(env);
register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(env);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 3747850..9ed645b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3620,8 +3620,6 @@
}
default -> {
Slogf.wtf(LOG_TAG, "Unhandled password complexity: " + passwordComplexity);
- // The following line is unreachable as Slogf.wtf crashes the process.
- // But we need this to avoid compilation error missing return statement.
return DEVICE_POLICY_STATE__PASSWORD_COMPLEXITY__COMPLEXITY_UNSPECIFIED;
}
}
@@ -13636,7 +13634,28 @@
setBackwardCompatibleUserRestriction(
caller, admin, key, enabledFromThisOwner, parent);
}
- logUserRestrictionCall(key, enabledFromThisOwner, parent, caller);
+ logUserRestrictionCall(key, enabledFromThisOwner, parent, caller, affectedUserId);
+ }
+
+ @Override
+ public void setUserRestrictionForUser(
+ @NonNull String systemEntity, String key, boolean enabled, @UserIdInt int targetUser) {
+ Objects.requireNonNull(systemEntity);
+
+ CallerIdentity caller = getCallerIdentity();
+ if (caller.getUid() != Process.SYSTEM_UID) {
+ throw new SecurityException("Only system services can call setUserRestrictionForUser"
+ + " on a target user: " + targetUser);
+ }
+ if (VERBOSE_LOG) {
+ Slogf.v(LOG_TAG, "Creating SystemEnforcingAdmin %s for calling package %s",
+ systemEntity, caller.getPackageName());
+ }
+ EnforcingAdmin admin = EnforcingAdmin.createSystemEnforcingAdmin(systemEntity);
+
+ setLocalUserRestrictionInternal(admin, key, enabled, targetUser);
+
+ logUserRestrictionCall(key, enabled, /* parent= */ false, caller, targetUser);
}
private void checkAdminCanSetRestriction(CallerIdentity caller, boolean parent, String key) {
@@ -13757,7 +13776,8 @@
setGlobalUserRestrictionInternal(admin, key, /* enabled= */ true);
- logUserRestrictionCall(key, /* enabled= */ true, /* parent= */ false, caller);
+ logUserRestrictionCall(key, /* enabled= */ true, /* parent= */ false, caller,
+ UserHandle.USER_ALL);
}
private void setLocalUserRestrictionInternal(
EnforcingAdmin admin, String key, boolean enabled, int userId) {
@@ -13793,7 +13813,7 @@
}
private void logUserRestrictionCall(
- String key, boolean enabled, boolean parent, CallerIdentity caller) {
+ String key, boolean enabled, boolean parent, CallerIdentity caller, int targetUserId) {
final int eventId = enabled
? DevicePolicyEnums.ADD_USER_RESTRICTION
: DevicePolicyEnums.REMOVE_USER_RESTRICTION;
@@ -13809,8 +13829,9 @@
SecurityLog.writeEvent(eventTag, caller.getPackageName(), caller.getUserId(), key);
}
- Slogf.i(LOG_TAG, "Changing user restriction %s to: %b caller: %s",
- key, enabled, caller.toString());
+ Slogf.i(LOG_TAG, "Changing user restriction %s on %s to: %b caller: %s",
+ key, (targetUserId == UserHandle.USER_ALL ? "all users" : ("user " + targetUserId)),
+ enabled, caller.toString());
}
@Override
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/EnforcingAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/EnforcingAdmin.java
index 02590f9..e65e513 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/EnforcingAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/EnforcingAdmin.java
@@ -21,7 +21,6 @@
import android.app.admin.Authority;
import android.app.admin.DeviceAdminAuthority;
import android.app.admin.DpcAuthority;
-import android.app.admin.PackagePermissionPolicyKey;
import android.app.admin.RoleAuthority;
import android.app.admin.UnknownAuthority;
import android.content.ComponentName;
@@ -57,23 +56,29 @@
static final String TAG = "EnforcingAdmin";
static final String ROLE_AUTHORITY_PREFIX = "role:";
+ static final String SYSTEM_AUTHORITY_PREFIX = "system:";
static final String DPC_AUTHORITY = "enterprise";
static final String DEVICE_ADMIN_AUTHORITY = "device_admin";
static final String DEFAULT_AUTHORITY = "default";
private static final String ATTR_PACKAGE_NAME = "package-name";
+ private static final String ATTR_SYSTEM_ENTITY = "system-entity";
private static final String ATTR_CLASS_NAME = "class-name";
private static final String ATTR_AUTHORITIES = "authorities";
private static final String ATTR_AUTHORITIES_SEPARATOR = ";";
private static final String ATTR_USER_ID = "user-id";
private static final String ATTR_IS_ROLE = "is-role";
+ private static final String ATTR_IS_SYSTEM = "is-system";
private final String mPackageName;
+ // Name of the system entity. Only used when mIsSystemAuthority is true.
+ private final String mSystemEntity;
// This is needed for DPCs and active admins
private final ComponentName mComponentName;
private Set<String> mAuthorities;
private final int mUserId;
private final boolean mIsRoleAuthority;
+ private final boolean mIsSystemAuthority;
private final ActiveAdmin mActiveAdmin;
static EnforcingAdmin createEnforcingAdmin(@NonNull String packageName, int userId,
@@ -106,6 +111,11 @@
userId, activeAdmin);
}
+ static EnforcingAdmin createSystemEnforcingAdmin(@NonNull String systemEntity) {
+ Objects.requireNonNull(systemEntity);
+ return new EnforcingAdmin(systemEntity);
+ }
+
static EnforcingAdmin createEnforcingAdmin(android.app.admin.EnforcingAdmin admin) {
Objects.requireNonNull(admin);
Authority authority = admin.getAuthority();
@@ -127,6 +137,7 @@
/* activeAdmin = */ null,
/* isRoleAuthority = */ true);
}
+ // TODO(b/324899199): Consider supporting android.app.admin.SystemAuthority.
return new EnforcingAdmin(admin.getPackageName(), admin.getComponentName(),
Set.of(), admin.getUserHandle().getIdentifier(),
/* activeAdmin = */ null);
@@ -159,9 +170,11 @@
Objects.requireNonNull(packageName);
Objects.requireNonNull(authorities);
- // Role authorities should not be using this constructor
+ // Role/System authorities should not be using this constructor
mIsRoleAuthority = false;
+ mIsSystemAuthority = false;
mPackageName = packageName;
+ mSystemEntity = null;
mComponentName = componentName;
mAuthorities = new HashSet<>(authorities);
mUserId = userId;
@@ -173,7 +186,9 @@
// Only role authorities use this constructor.
mIsRoleAuthority = true;
+ mIsSystemAuthority = false;
mPackageName = packageName;
+ mSystemEntity = null;
mUserId = userId;
mComponentName = null;
// authorities will be loaded when needed
@@ -181,6 +196,21 @@
mActiveAdmin = activeAdmin;
}
+ /** Constructor for System authorities. */
+ private EnforcingAdmin(@NonNull String systemEntity) {
+ Objects.requireNonNull(systemEntity);
+
+ // Only system authorities use this constructor.
+ mIsSystemAuthority = true;
+ mIsRoleAuthority = false;
+ mPackageName = null;
+ mSystemEntity = systemEntity;
+ mUserId = UserHandle.USER_SYSTEM;
+ mComponentName = null;
+ mAuthorities = getSystemAuthority(systemEntity);
+ mActiveAdmin = null;
+ }
+
private EnforcingAdmin(
String packageName, @Nullable ComponentName componentName, Set<String> authorities,
int userId, @Nullable ActiveAdmin activeAdmin, boolean isRoleAuthority) {
@@ -188,7 +218,9 @@
Objects.requireNonNull(authorities);
mIsRoleAuthority = isRoleAuthority;
+ mIsSystemAuthority = false;
mPackageName = packageName;
+ mSystemEntity = null;
mComponentName = componentName;
mAuthorities = new HashSet<>(authorities);
mUserId = userId;
@@ -204,6 +236,18 @@
return authorities.isEmpty() ? Set.of(DEFAULT_AUTHORITY) : authorities;
}
+ /**
+ * Returns a set of authorities for system authority.
+ *
+ * <p>Note that a system authority enforcing admin has only one authority that has the package
+ * name of the calling system service. Therefore, the returned set always contains one element.
+ */
+ private static Set<String> getSystemAuthority(String systemEntity) {
+ Set<String> authorities = new HashSet<>();
+ authorities.add(SYSTEM_AUTHORITY_PREFIX + systemEntity);
+ return authorities;
+ }
+
// TODO(b/259042794): move this logic to RoleManagerLocal
private static Set<String> getRoles(String packageName, int userId) {
RoleManagerLocal roleManagerLocal = LocalManagerRegistry.getManager(
@@ -264,6 +308,7 @@
} else if (mAuthorities.contains(DEVICE_ADMIN_AUTHORITY)) {
authority = DeviceAdminAuthority.DEVICE_ADMIN_AUTHORITY;
} else {
+ // For now, System Authority returns UNKNOWN_AUTHORITY.
authority = UnknownAuthority.UNKNOWN_AUTHORITY;
}
return new android.app.admin.EnforcingAdmin(
@@ -291,8 +336,10 @@
if (o == null || getClass() != o.getClass()) return false;
EnforcingAdmin other = (EnforcingAdmin) o;
return Objects.equals(mPackageName, other.mPackageName)
+ && Objects.equals(mSystemEntity, other.mSystemEntity)
&& Objects.equals(mComponentName, other.mComponentName)
&& Objects.equals(mIsRoleAuthority, other.mIsRoleAuthority)
+ && (mIsSystemAuthority == other.mIsSystemAuthority)
&& hasMatchingAuthorities(this, other);
}
@@ -307,6 +354,8 @@
public int hashCode() {
if (mIsRoleAuthority) {
return Objects.hash(mPackageName, mUserId);
+ } else if (mIsSystemAuthority) {
+ return Objects.hash(mSystemEntity);
} else {
return Objects.hash(
mComponentName == null ? mPackageName : mComponentName,
@@ -318,8 +367,12 @@
void saveToXml(TypedXmlSerializer serializer) throws IOException {
serializer.attribute(/* namespace= */ null, ATTR_PACKAGE_NAME, mPackageName);
serializer.attributeBoolean(/* namespace= */ null, ATTR_IS_ROLE, mIsRoleAuthority);
+ serializer.attributeBoolean(/* namespace= */ null, ATTR_IS_SYSTEM, mIsSystemAuthority);
serializer.attributeInt(/* namespace= */ null, ATTR_USER_ID, mUserId);
- if (!mIsRoleAuthority) {
+ if (mIsSystemAuthority) {
+ serializer.attribute(/* namespace= */ null, ATTR_SYSTEM_ENTITY, mSystemEntity);
+ }
+ if (!mIsRoleAuthority && !mIsSystemAuthority) {
if (mComponentName != null) {
serializer.attribute(
/* namespace= */ null, ATTR_CLASS_NAME, mComponentName.getClassName());
@@ -336,7 +389,10 @@
static EnforcingAdmin readFromXml(TypedXmlPullParser parser)
throws XmlPullParserException {
String packageName = parser.getAttributeValue(/* namespace= */ null, ATTR_PACKAGE_NAME);
+ String systemEntity = parser.getAttributeValue(/* namespace= */ null, ATTR_SYSTEM_ENTITY);
boolean isRoleAuthority = parser.getAttributeBoolean(/* namespace= */ null, ATTR_IS_ROLE);
+ boolean isSystemAuthority = parser.getAttributeBoolean(
+ /* namespace= */ null, ATTR_IS_SYSTEM, /* defaultValue= */ false);
String authoritiesStr = parser.getAttributeValue(/* namespace= */ null, ATTR_AUTHORITIES);
int userId = parser.getAttributeInt(/* namespace= */ null, ATTR_USER_ID);
@@ -348,6 +404,13 @@
}
// TODO(b/281697976): load active admin
return new EnforcingAdmin(packageName, userId, null);
+ } else if (isSystemAuthority) {
+ if (systemEntity == null) {
+ Slogf.wtf(TAG, "Error parsing EnforcingAdmin with SystemAuthority, "
+ + "systemEntity is null.");
+ return null;
+ }
+ return new EnforcingAdmin(systemEntity);
} else {
if (packageName == null || authoritiesStr == null) {
Slogf.wtf(TAG, "Error parsing EnforcingAdmin, packageName is "
@@ -381,6 +444,10 @@
sb.append(mUserId);
sb.append(", mIsRoleAuthority= ");
sb.append(mIsRoleAuthority);
+ sb.append(", mIsSystemAuthority= ");
+ sb.append(mIsSystemAuthority);
+ sb.append(", mSystemEntity = ");
+ sb.append(mSystemEntity);
sb.append(" }");
return sb.toString();
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
index c582a46..dd049303 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
@@ -663,7 +663,7 @@
}
}
if (DEBUG) {
- Slogf.d(TAG, "Adding audit %d events to % already present in the buffer",
+ Slogf.d(TAG, "Adding audit %d events to %d already present in the buffer",
events.size(), mAuditLogEventBuffer.size());
}
mAuditLogEventBuffer.addAll(events);
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java
index dd3b33e..8ce2422 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java
@@ -23,7 +23,6 @@
import static android.view.WindowManager.DISPLAY_IME_POLICY_HIDE;
import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.internal.inputmethod.SoftInputShowHideReason.HIDE_WHEN_INPUT_TARGET_INVISIBLE;
@@ -41,6 +40,7 @@
import static org.mockito.ArgumentMatchers.notNull;
+import android.annotation.UserIdInt;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -50,7 +50,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.internal.annotations.GuardedBy;
-import com.android.server.wm.ImeTargetChangeListener;
import com.android.server.wm.WindowManagerInternal;
import org.junit.Before;
@@ -68,7 +67,6 @@
@RunWith(AndroidJUnit4.class)
public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTestBase {
private ImeVisibilityStateComputer mComputer;
- private ImeTargetChangeListener mListener;
private int mImeDisplayPolicy = DISPLAY_IME_POLICY_LOCAL;
@Before
@@ -84,12 +82,14 @@
public ImeDisplayValidator getImeValidator() {
return displayId -> mImeDisplayPolicy;
}
+
+ @UserIdInt
+ @Override
+ public int getUserId() {
+ return mUserId;
+ }
};
- ArgumentCaptor<ImeTargetChangeListener> captor = ArgumentCaptor.forClass(
- ImeTargetChangeListener.class);
- verify(mMockWindowManagerInternal).setInputMethodTargetChangeListener(captor.capture());
mComputer = new ImeVisibilityStateComputer(mInputMethodManagerService, injector);
- mListener = captor.getValue();
}
@Test
@@ -298,28 +298,32 @@
@Test
public void testOnApplyImeVisibilityFromComputer() {
synchronized (ImfLock.class) {
- final IBinder testImeTargetOverlay = new Binder();
final IBinder testImeInputTarget = new Binder();
// Simulate a test IME input target was visible.
- mListener.onImeInputTargetVisibilityChanged(testImeInputTarget, true, false);
+ mComputer.onImeInputTargetVisibilityChanged(testImeInputTarget,
+ true /* visibleAndNotRemoved */);
// Simulate a test IME layering target overlay fully occluded the IME input target.
- mListener.onImeTargetOverlayVisibilityChanged(testImeTargetOverlay,
- TYPE_APPLICATION_OVERLAY, true, false);
- mListener.onImeInputTargetVisibilityChanged(testImeInputTarget, false, false);
+ mComputer.setHasVisibleImeLayeringOverlay(true /* visibleAndNotRemoved */);
+ mComputer.onImeInputTargetVisibilityChanged(testImeInputTarget,
+ false /* visibleAndNotRemoved */);
final ArgumentCaptor<IBinder> targetCaptor = ArgumentCaptor.forClass(IBinder.class);
final ArgumentCaptor<ImeVisibilityResult> resultCaptor = ArgumentCaptor.forClass(
ImeVisibilityResult.class);
+ final ArgumentCaptor<Integer> userIdCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mInputMethodManagerService).onApplyImeVisibilityFromComputerLocked(
- targetCaptor.capture(), notNull() /* statsToken */, resultCaptor.capture());
+ targetCaptor.capture(), notNull() /* statsToken */, resultCaptor.capture(),
+ userIdCaptor.capture());
final IBinder imeInputTarget = targetCaptor.getValue();
final ImeVisibilityResult result = resultCaptor.getValue();
+ final int userId = userIdCaptor.getValue();
// Verify the computer will callback hiding IME state to IMMS.
assertThat(imeInputTarget).isEqualTo(testImeInputTarget);
assertThat(result.getState()).isEqualTo(STATE_HIDE_IME_EXPLICIT);
assertThat(result.getReason()).isEqualTo(HIDE_WHEN_INPUT_TARGET_INVISIBLE);
+ assertThat(userId).isEqualTo(mUserId);
}
}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodBindingControllerTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodBindingControllerTest.java
index 1e3b7e9..e552621 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodBindingControllerTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodBindingControllerTest.java
@@ -79,10 +79,8 @@
// from system.
synchronized (ImfLock.class) {
mBindingController =
- new InputMethodBindingController(
- mInputMethodManagerService.getCurrentImeUserIdLocked(),
- mInputMethodManagerService, mImeConnectionBindFlags,
- mCountDownLatch);
+ new InputMethodBindingController(mUserId, mInputMethodManagerService,
+ mImeConnectionBindFlags, mCountDownLatch);
}
}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceRestrictImeAmountTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceRestrictImeAmountTest.java
index 2ea2e22..a86d61bb 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceRestrictImeAmountTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceRestrictImeAmountTest.java
@@ -122,8 +122,8 @@
private List<InputMethodInfo> filterInputMethodServices(List<ResolveInfo> resolveInfoList,
List<String> enabledComponents) {
- final InputMethodMap methodMap = InputMethodManagerService.filterInputMethodServices(
- AdditionalSubtypeMap.EMPTY_MAP, enabledComponents, mContext, resolveInfoList);
+ final var methodMap = InputMethodManagerService.filterInputMethodServices(
+ enabledComponents, mContext, resolveInfoList);
return methodMap.values();
}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
index 461697c..9a25104 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
@@ -269,15 +269,21 @@
LocalServices.removeServiceForTest(InputMethodManagerInternal.class);
lifecycle.onStart();
+ final var userData = mInputMethodManagerService.getUserData(mUserId);
+
// Certain tests rely on TEST_IME_ID that is installed with AndroidTest.xml.
// TODO(b/352615651): Consider just synthesizing test InputMethodInfo then injecting it.
AdditionalSubtypeMapRepository.initializeIfNecessary(mUserId);
- final var settings = InputMethodManagerService.queryInputMethodServicesInternal(mContext,
- mUserId, AdditionalSubtypeMapRepository.get(mUserId), DirectBootAwareness.AUTO);
+ final var rawMethodMap = InputMethodManagerService.queryRawInputMethodServiceMap(mContext,
+ mUserId);
+ userData.mRawInputMethodMap.set(rawMethodMap);
+ final var settings = InputMethodSettings.create(rawMethodMap.toInputMethodMap(
+ AdditionalSubtypeMap.EMPTY_MAP, DirectBootAwareness.AUTO, true /* userUnlocked */),
+ mUserId);
InputMethodSettingsRepository.put(mUserId, settings);
// Emulate that the user initialization is done.
- mInputMethodManagerService.getUserData(mUserId).mBackgroundLoadLatch.countDown();
+ userData.mBackgroundLoadLatch.countDown();
// After this boot phase, services can broadcast Intents.
lifecycle.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java
index d59f28b..b984624 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java
@@ -19,6 +19,11 @@
import static com.google.common.truth.Truth.assertThat;
import android.platform.test.ravenwood.RavenwoodRule;
+import android.view.WindowManager;
+
+import androidx.annotation.NonNull;
+
+import com.android.server.wm.WindowManagerInternal;
import org.junit.After;
import org.junit.Before;
@@ -43,20 +48,43 @@
@Mock
private InputMethodManagerService mMockInputMethodManagerService;
+ @Mock
+ private WindowManagerInternal mMockWindowManagerInternal;
+
+ @NonNull
private IntFunction<InputMethodBindingController> mBindingControllerFactory;
+ @NonNull
+ private IntFunction<ImeVisibilityStateComputer> mVisibilityStateComputerFactory;
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
SecureSettingsWrapper.startTestMode();
- mBindingControllerFactory = new IntFunction<InputMethodBindingController>() {
+ mBindingControllerFactory = userId ->
+ new InputMethodBindingController(userId, mMockInputMethodManagerService);
- @Override
- public InputMethodBindingController apply(int userId) {
- return new InputMethodBindingController(userId, mMockInputMethodManagerService);
- }
- };
+ mVisibilityStateComputerFactory = userId -> new ImeVisibilityStateComputer(
+ mMockInputMethodManagerService,
+ new ImeVisibilityStateComputer.Injector() {
+ @NonNull
+ @Override
+ public WindowManagerInternal getWmService() {
+ return mMockWindowManagerInternal;
+ }
+
+ @NonNull
+ @Override
+ public InputMethodManagerService.ImeDisplayValidator getImeValidator() {
+ return displayId -> WindowManager.DISPLAY_IME_POLICY_LOCAL;
+ }
+
+ @Override
+ public int getUserId() {
+ return userId;
+ }
+ });
}
@After
@@ -69,7 +97,8 @@
public void testUserDataRepository_removesUserInfoOnUserRemovedEvent() {
// Create UserDataRepository
final var repository = new UserDataRepository(
- userId -> new InputMethodBindingController(userId, mMockInputMethodManagerService));
+ userId -> new InputMethodBindingController(userId, mMockInputMethodManagerService),
+ mVisibilityStateComputerFactory);
// Add one UserData ...
final var userData = repository.getOrCreate(ANY_USER_ID);
@@ -85,7 +114,8 @@
@Test
public void testGetOrCreate() {
- final var repository = new UserDataRepository(mBindingControllerFactory);
+ final var repository = new UserDataRepository(mBindingControllerFactory,
+ mVisibilityStateComputerFactory);
final var userData = repository.getOrCreate(ANY_USER_ID);
assertThat(userData.mUserId).isEqualTo(ANY_USER_ID);
@@ -96,6 +126,7 @@
// Assert UserDataRepository called the InputMethodBindingController creator function.
assertThat(allUserData.get(0).mBindingController.getUserId()).isEqualTo(ANY_USER_ID);
+ assertThat(allUserData.get(0).mVisibilityStateComputer.getUserId()).isEqualTo(ANY_USER_ID);
}
private List<UserData> collectUserData(UserDataRepository repository) {
diff --git a/services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java
index fb73aff..f3cd0c9 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java
@@ -693,6 +693,21 @@
}
@Test
+ public void testGetPreset() {
+ int preset = Settings.System.SCREEN_BRIGHTNESS_AUTOMATIC_DIM;
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS_FOR_ALS, preset);
+ setUpResources();
+ DisplayDeviceConfig ddc = new DdcBuilder()
+ .setAutoBrightnessLevels(AUTO_BRIGHTNESS_MODE_DEFAULT, preset, DISPLAY_LEVELS)
+ .setAutoBrightnessLevelsLux(AUTO_BRIGHTNESS_MODE_DEFAULT, preset, LUX_LEVELS)
+ .build();
+ BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(mContext, ddc,
+ AUTO_BRIGHTNESS_MODE_DEFAULT, /* displayWhiteBalanceController= */ null);
+ assertEquals(preset, strategy.getPreset());
+ }
+
+ @Test
public void testAutoBrightnessModeAndPreset() {
int mode = AUTO_BRIGHTNESS_MODE_DOZE;
int preset = Settings.System.SCREEN_BRIGHTNESS_AUTOMATIC_DIM;
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
index 8ed38a6..b5278a5 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -936,6 +936,9 @@
@Test
public void testSetScreenOffBrightnessSensorDisabled_DisplayIsOn() {
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS_MODE,
+ Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
@@ -948,6 +951,9 @@
@Test
public void testSetScreenOffBrightnessSensorDisabled_DisplayIsAFollower() {
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS_MODE,
+ Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_OFF;
@@ -960,6 +966,24 @@
}
@Test
+ public void testSetScreenOffBrightnessSensorDisabled_AutoBrightnessInDoze() {
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS_MODE,
+ Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
+ mContext.getOrCreateTestableResources().addOverride(
+ com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing, true);
+ mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ dpr.policy = DisplayPowerRequest.POLICY_DOZE;
+
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
+ .setLightSensorEnabled(false);
+ }
+
+ @Test
public void testStopScreenOffBrightnessSensorControllerWhenDisplayDeviceChanges() {
// New display device
setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class),
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
index d7936fe..c069875 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
@@ -545,17 +545,18 @@
DisplayDeviceConfig displayDeviceConfig = mock(DisplayDeviceConfig.class);
Handler handler = mock(Handler.class);
BrightnessMappingStrategy brightnessMappingStrategy = mock(BrightnessMappingStrategy.class);
- boolean isEnabled = true;
+ boolean isDisplayEnabled = true;
int leadDisplayId = 2;
mDisplayBrightnessController.setUpAutoBrightness(automaticBrightnessController,
- sensorManager, displayDeviceConfig, handler, brightnessMappingStrategy, isEnabled,
- leadDisplayId);
+ sensorManager, displayDeviceConfig, handler, brightnessMappingStrategy,
+ isDisplayEnabled, leadDisplayId);
assertEquals(automaticBrightnessController,
mDisplayBrightnessController.mAutomaticBrightnessController);
verify(automaticBrightnessStrategy).setAutomaticBrightnessController(
automaticBrightnessController);
verify(autoBrightnessFallbackStrategy).setupAutoBrightnessFallbackSensor(sensorManager,
- displayDeviceConfig, handler, brightnessMappingStrategy, isEnabled, leadDisplayId);
+ displayDeviceConfig, handler, brightnessMappingStrategy, isDisplayEnabled,
+ leadDisplayId);
}
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessLowLuxModifierTest.kt b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessLowLuxModifierTest.kt
index d672435..6929690 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessLowLuxModifierTest.kt
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessLowLuxModifierTest.kt
@@ -225,5 +225,37 @@
assertThat(modifier.brightnessReason).isEqualTo(BrightnessReason.MODIFIER_MIN_LUX)
assertThat(modifier.brightnessLowerBound).isEqualTo(LOW_LUX_BRIGHTNESS)
}
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_EVEN_DIMMER)
+ fun testUserSwitch() {
+ // nits: 0.5 -> backlight 0.01 -> brightness -> 0.05
+ whenever(mockDisplayDeviceConfig.getBacklightFromNits(/* nits= */ 0.5f))
+ .thenReturn(0.01f)
+ whenever(mockDisplayDeviceConfig.getBrightnessFromBacklight(/* backlight = */ 0.01f))
+ .thenReturn(0.05f)
+
+ Settings.Secure.putIntForUser(context.contentResolver,
+ Settings.Secure.EVEN_DIMMER_ACTIVATED, 0, USER_ID) // off
+ Settings.Secure.putFloatForUser(context.contentResolver,
+ Settings.Secure.EVEN_DIMMER_MIN_NITS, 1.0f, USER_ID)
+
+ modifier.recalculateLowerBound()
+
+ assertThat(modifier.isActive).isFalse()
+ assertThat(modifier.brightnessLowerBound).isEqualTo(TRANSITION_POINT)
+ assertThat(modifier.brightnessReason).isEqualTo(0) // no reason - i.e. off
+
+ Settings.Secure.putIntForUser(context.contentResolver,
+ Settings.Secure.EVEN_DIMMER_ACTIVATED, 1, USER_ID) // on
+ Settings.Secure.putFloatForUser(context.contentResolver,
+ Settings.Secure.EVEN_DIMMER_MIN_NITS, 0.5f, USER_ID)
+ modifier.onSwitchUser()
+
+ assertThat(modifier.isActive).isTrue()
+ assertThat(modifier.brightnessReason).isEqualTo(
+ BrightnessReason.MODIFIER_MIN_USER_SET_LOWER_BOUND)
+ assertThat(modifier.brightnessLowerBound).isEqualTo(0.05f)
+ }
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrBrightnessModifierTest.kt b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrBrightnessModifierTest.kt
index 0ed96ae..bb025cc 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrBrightnessModifierTest.kt
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrBrightnessModifierTest.kt
@@ -16,7 +16,10 @@
package com.android.server.display.brightness.clamper
+import android.content.Context
+import android.database.ContentObserver
import android.hardware.display.DisplayManagerInternal
+import android.net.Uri
import android.os.IBinder
import android.os.PowerManager.BRIGHTNESS_MAX
import android.util.Spline
@@ -51,7 +54,7 @@
private val stoppedClock = OffsettableClock.Stopped()
private val testHandler = TestHandler(null, stoppedClock)
- private val testInjector = TestInjector()
+ private val testInjector = TestInjector(mock<Context>())
private val mockChangeListener = mock<ClamperChangeListener>()
private val mockDisplayDeviceConfig = mock<DisplayDeviceConfig>()
private val mockDisplayBinder = mock<IBinder>()
@@ -63,14 +66,14 @@
private val dummyData = createDisplayDeviceData(mockDisplayDeviceConfig, mockDisplayBinder)
@Test
- fun `change listener is not called on init`() {
+ fun changeListenerIsNotCalledOnInit() {
initHdrModifier()
verify(mockChangeListener, never()).onChanged()
}
@Test
- fun `hdr listener registered on init if hdr data is present`() {
+ fun hdrListenerRegisteredOnInit_hdrDataPresent() {
initHdrModifier()
assertThat(testInjector.registeredHdrListener).isNotNull()
@@ -78,22 +81,19 @@
}
@Test
- fun `hdr listener not registered on init if hdr data is missing`() {
- initHdrModifier(null)
-
- testHandler.flush()
+ fun hdrListenerNotRegisteredOnInit_hdrDataMissing() {
+ initHdrModifier(hdrBrightnessData = null)
assertThat(testInjector.registeredHdrListener).isNull()
assertThat(testInjector.registeredToken).isNull()
}
@Test
- fun `unsubscribes hdr listener when display changed with no hdr data`() {
+ fun unsubscribeHdrListener_displayChangedWithNoHdrData() {
initHdrModifier()
whenever(mockDisplayDeviceConfig.hdrBrightnessData).thenReturn(null)
modifier.onDisplayChanged(dummyData)
- testHandler.flush()
assertThat(testInjector.registeredHdrListener).isNull()
assertThat(testInjector.registeredToken).isNull()
@@ -101,12 +101,11 @@
}
@Test
- fun `resubscribes hdr listener when display changed with different token`() {
+ fun resubscribesHdrListener_displayChangedWithDifferentToken() {
initHdrModifier()
modifier.onDisplayChanged(
createDisplayDeviceData(mockDisplayDeviceConfig, mockDisplayBinderOther))
- testHandler.flush()
assertThat(testInjector.registeredHdrListener).isNotNull()
assertThat(testInjector.registeredToken).isEqualTo(mockDisplayBinderOther)
@@ -114,7 +113,28 @@
}
@Test
- fun `test NO_HDR mode`() {
+ fun contentObserverNotRegisteredOnInit_hdrDataMissing() {
+ initHdrModifier(null)
+
+ assertThat(testInjector.registeredContentObserver).isNull()
+ }
+
+ @Test
+ fun contentObserverNotRegisteredOnInit_allowedInLowPowerMode() {
+ initHdrModifier(createHdrBrightnessData(allowInLowPowerMode = true))
+
+ assertThat(testInjector.registeredContentObserver).isNull()
+ }
+
+ @Test
+ fun contentObserverRegisteredOnInit_notAllowedInLowPowerMode() {
+ initHdrModifier(createHdrBrightnessData(allowInLowPowerMode = false))
+
+ assertThat(testInjector.registeredContentObserver).isNotNull()
+ }
+
+ @Test
+ fun testNoHdrMode() {
initHdrModifier()
// screen size = 10_000
setupDisplay(width = 100, height = 100, hdrBrightnessData = createHdrBrightnessData(
@@ -131,7 +151,7 @@
}
@Test
- fun `test NBM_HDR mode`() {
+ fun testNbmHdrMode() {
initHdrModifier()
// screen size = 10_000
val transitionPoint = 0.55f
@@ -157,7 +177,7 @@
}
@Test
- fun `test HBM_HDR mode`() {
+ fun testHbmHdrMode() {
initHdrModifier()
// screen size = 10_000
setupDisplay(width = 100, height = 100, hdrBrightnessData = createHdrBrightnessData(
@@ -182,7 +202,7 @@
}
@Test
- fun `test display change no HDR content`() {
+ fun testDisplayChange_noHdrContent() {
initHdrModifier()
setupDisplay(width = 100, height = 100)
assertModifierState()
@@ -195,7 +215,7 @@
}
@Test
- fun `test display change with HDR content`() {
+ fun testDisplayChange_hdrContent() {
initHdrModifier()
setupDisplay(width = 100, height = 100)
setupHdrLayer(width = 100, height = 100, maxHdrRatio = 5f)
@@ -218,7 +238,7 @@
}
@Test
- fun `test ambient lux decrease above maxBrightnessLimits no HDR`() {
+ fun testSetAmbientLux_decreaseAboveMaxBrightnessLimitNoHdr() {
initHdrModifier()
modifier.setAmbientLux(1000f)
setupDisplay(width = 100, height = 100, hdrBrightnessData = createHdrBrightnessData(
@@ -234,7 +254,7 @@
}
@Test
- fun `test ambient lux decrease above maxBrightnessLimits with HDR`() {
+ fun testSetAmbientLux_decreaseAboveMaxBrightnessLimitWithHdr() {
initHdrModifier()
modifier.setAmbientLux(1000f)
setupDisplay(width = 200, height = 200, hdrBrightnessData = createHdrBrightnessData(
@@ -260,7 +280,7 @@
}
@Test
- fun `test ambient lux decrease below maxBrightnessLimits no HDR`() {
+ fun testSetAmbientLux_decreaseBelowMaxBrightnessLimitNoHdr() {
initHdrModifier()
modifier.setAmbientLux(1000f)
setupDisplay(width = 100, height = 100, hdrBrightnessData = createHdrBrightnessData(
@@ -276,7 +296,7 @@
}
@Test
- fun `test ambient lux decrease below maxBrightnessLimits with HDR`() {
+ fun testSetAmbientLux_decreaseBelowMaxBrightnessLimitWithHdr() {
initHdrModifier()
modifier.setAmbientLux(1000f)
val maxBrightness = 0.6f
@@ -322,6 +342,23 @@
)
}
+ @Test
+ fun testLowPower_notAllowedInLowPower() {
+ initHdrModifier()
+ setupDisplay(width = 100, height = 100, hdrBrightnessData = createHdrBrightnessData(
+ allowInLowPowerMode = false
+ ))
+ setupHdrLayer(width = 100, height = 100)
+ clearInvocations(mockChangeListener)
+
+ testInjector.isLowPower = true
+ testInjector.registeredContentObserver!!.onChange(true)
+
+ verify(mockChangeListener).onChanged()
+ assertModifierState()
+ }
+
+ // Helper functions
private fun setupHdrLayer(width: Int = 100, height: Int = 100, maxHdrRatio: Float = 0.8f) {
testInjector.registeredHdrListener!!.onHdrInfoChanged(
mockDisplayBinder, 1, width, height, 0, maxHdrRatio
@@ -345,7 +382,6 @@
width = width,
height = height
))
- testHandler.flush()
}
private fun initHdrModifier(hdrBrightnessData: HdrBrightnessData? = createHdrBrightnessData()) {
@@ -384,9 +420,12 @@
assertThat(stateBuilder.customAnimationRate).isEqualTo(animationRate)
}
- internal class TestInjector : Injector() {
+ internal class TestInjector(context: Context) : Injector(context) {
var registeredHdrListener: SurfaceControlHdrLayerInfoListener? = null
var registeredToken: IBinder? = null
+ var registeredContentObserver: ContentObserver? = null
+
+ var isLowPower: Boolean = false
override fun registerHdrListener(
listener: SurfaceControlHdrLayerInfoListener, token: IBinder
@@ -401,5 +440,17 @@
registeredHdrListener = null
registeredToken = null
}
+
+ override fun registerContentObserver(observer: ContentObserver, uri: Uri) {
+ registeredContentObserver = observer
+ }
+
+ override fun unregisterContentObserver(observer: ContentObserver) {
+ registeredContentObserver = null
+ }
+
+ override fun isLowPowerMode(): Boolean {
+ return isLowPower
+ }
}
}
\ No newline at end of file
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/LightSensorControllerTest.kt b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/LightSensorControllerTest.kt
index f59e127..79b99b5 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/LightSensorControllerTest.kt
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/LightSensorControllerTest.kt
@@ -29,6 +29,7 @@
import com.android.server.display.config.createSensorData
import com.android.server.display.utils.AmbientFilter
import org.junit.Before
+import org.junit.Test
import org.mockito.kotlin.any
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.eq
@@ -62,31 +63,35 @@
mockLightSensorListener, mockHandler, testInjector)
}
- fun `does not register light sensor if is not configured`() {
+ @Test
+ fun doesNotRegisterLightSensorIfNotConfigured() {
controller.restart()
verifyNoMoreInteractions(mockSensorManager, mockAmbientFilter, mockLightSensorListener)
}
- fun `does not register light sensor if missing`() {
+ @Test
+ fun doesNotRegisterLightSensorIfMissing() {
controller.configure(dummySensorData, DISPLAY_ID)
controller.restart()
verifyNoMoreInteractions(mockSensorManager, mockAmbientFilter, mockLightSensorListener)
}
- fun `register light sensor if configured and present`() {
+ @Test
+ fun registerLightSensorIfConfiguredAndPresent() {
testInjector.lightSensor = TestUtils
.createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT)
controller.configure(dummySensorData, DISPLAY_ID)
controller.restart()
verify(mockSensorManager).registerListener(any(),
- testInjector.lightSensor, LIGHT_SENSOR_RATE * 1000, mockHandler)
+ eq(testInjector.lightSensor), eq(LIGHT_SENSOR_RATE * 1000), eq(mockHandler))
verifyNoMoreInteractions(mockSensorManager, mockAmbientFilter, mockLightSensorListener)
}
- fun `register light sensor once if not changed`() {
+ @Test
+ fun registerLightSensorOnceIfNotChanged() {
testInjector.lightSensor = TestUtils
.createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT)
controller.configure(dummySensorData, DISPLAY_ID)
@@ -95,11 +100,12 @@
controller.restart()
verify(mockSensorManager).registerListener(any(),
- testInjector.lightSensor, LIGHT_SENSOR_RATE * 1000, mockHandler)
+ eq(testInjector.lightSensor), eq(LIGHT_SENSOR_RATE * 1000), eq(mockHandler))
verifyNoMoreInteractions(mockSensorManager, mockAmbientFilter, mockLightSensorListener)
}
- fun `register new light sensor and unregister old if changed`() {
+ @Test
+ fun registerNewAndUnregisterOldLightSensorIfChanged() {
val lightSensor1 = TestUtils
.createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT)
testInjector.lightSensor = lightSensor1
@@ -112,19 +118,21 @@
controller.configure(dummySensorData, DISPLAY_ID)
controller.restart()
- inOrder {
+ inOrder(mockSensorManager, mockAmbientFilter, mockLightSensorListener) {
verify(mockSensorManager).registerListener(any(),
- lightSensor1, LIGHT_SENSOR_RATE * 1000, mockHandler)
- verify(mockSensorManager).unregisterListener(any<SensorEventListener>())
+ eq(lightSensor1), eq(LIGHT_SENSOR_RATE * 1000), eq(mockHandler))
+ verify(mockSensorManager).registerListener(any(),
+ eq(lightSensor2), eq(LIGHT_SENSOR_RATE * 1000), eq(mockHandler))
+ verify(mockSensorManager).unregisterListener(any<SensorEventListener>(),
+ eq(lightSensor1))
verify(mockAmbientFilter).clear()
verify(mockLightSensorListener).onAmbientLuxChange(LightSensorController.INVALID_LUX)
- verify(mockSensorManager).registerListener(any(),
- lightSensor2, LIGHT_SENSOR_RATE * 1000, mockHandler)
}
verifyNoMoreInteractions(mockSensorManager, mockAmbientFilter, mockLightSensorListener)
}
- fun `notifies listener on ambient lux change`() {
+ @Test
+ fun notifiesListenerOnAmbientLuxChange() {
val expectedLux = 40f
val eventLux = 50
val eventTime = 60L
@@ -141,7 +149,7 @@
listener.onSensorChanged(TestUtils.createSensorEvent(testInjector.lightSensor,
eventLux, eventTime * 1_000_000))
- inOrder {
+ inOrder(mockAmbientFilter, mockLightSensorListener) {
verify(mockAmbientFilter).addValue(eventTime, eventLux.toFloat())
verify(mockLightSensorListener).onAmbientLuxChange(expectedLux)
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutoBrightnessFallbackStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutoBrightnessFallbackStrategyTest.java
index bb24c0f..99dfa73 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutoBrightnessFallbackStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutoBrightnessFallbackStrategyTest.java
@@ -16,15 +16,22 @@
package com.android.server.display.brightness.strategy;
+import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT;
+import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE;
+import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_OFF;
+
+import static com.android.server.display.layout.Layout.NO_LEAD_DISPLAY;
import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.hardware.display.DisplayManagerInternal;
import android.os.Handler;
+import android.os.PowerManager;
+import android.view.Display;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -35,6 +42,7 @@
import com.android.server.display.ScreenOffBrightnessSensorController;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.brightness.StrategyExecutionRequest;
+import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import org.junit.Before;
import org.junit.Test;
@@ -53,9 +61,24 @@
@Mock
private ScreenOffBrightnessSensorController mScreenOffBrightnessSensorController;
+ @Mock
+ private SensorManager mSensorManager;
+
+ @Mock
+ private DisplayDeviceConfig mDisplayDeviceConfig;
+
+ @Mock
+ private Handler mHandler;
+
+ @Mock
+ private BrightnessMappingStrategy mBrightnessMappingStrategy;
+
@Before
public void before() {
MockitoAnnotations.initMocks(this);
+ int[] sensorValueToLux = new int[]{50, 100};
+ when(mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux())
+ .thenReturn(sensorValueToLux);
mAutoBrightnessFallbackStrategy = new AutoBrightnessFallbackStrategy(
new AutoBrightnessFallbackStrategy.Injector() {
@Override
@@ -78,20 +101,11 @@
@Test
public void testUpdateBrightnessWhenScreenDozeStateIsRequested() {
- // Setup the argument mocks
- SensorManager sensorManager = mock(SensorManager.class);
- DisplayDeviceConfig displayDeviceConfig = mock(DisplayDeviceConfig.class);
- Handler handler = mock(Handler.class);
- BrightnessMappingStrategy brightnessMappingStrategy = mock(BrightnessMappingStrategy.class);
- boolean isEnabled = true;
+ boolean isDisplayEnabled = true;
int leadDisplayId = 2;
-
- int[] sensorValueToLux = new int[]{50, 100};
- when(displayDeviceConfig.getScreenOffBrightnessSensorValueToLux()).thenReturn(
- sensorValueToLux);
-
- mAutoBrightnessFallbackStrategy.setupAutoBrightnessFallbackSensor(sensorManager,
- displayDeviceConfig, handler, brightnessMappingStrategy, isEnabled, leadDisplayId);
+ mAutoBrightnessFallbackStrategy.setupAutoBrightnessFallbackSensor(mSensorManager,
+ mDisplayDeviceConfig,
+ mHandler, mBrightnessMappingStrategy, isDisplayEnabled, leadDisplayId);
assertEquals(mScreenOffBrightnessSensor,
mAutoBrightnessFallbackStrategy.mScreenOffBrightnessSensor);
@@ -119,4 +133,157 @@
assertEquals(updatedDisplayBrightnessState, expectedDisplayBrightnessState);
}
+ @Test
+ public void testPostProcess_EnableSensor_PolicyOff() {
+ boolean isDisplayEnabled = true;
+ int leadDisplayId = NO_LEAD_DISPLAY;
+ mAutoBrightnessFallbackStrategy.setupAutoBrightnessFallbackSensor(mSensorManager,
+ mDisplayDeviceConfig,
+ mHandler, mBrightnessMappingStrategy, isDisplayEnabled, leadDisplayId);
+
+ DisplayManagerInternal.DisplayPowerRequest dpr =
+ new DisplayManagerInternal.DisplayPowerRequest();
+ dpr.policy = POLICY_OFF;
+ StrategySelectionNotifyRequest ssnr = new StrategySelectionNotifyRequest(dpr,
+ Display.STATE_OFF, mAutoBrightnessFallbackStrategy,
+ /* lastUserSetScreenBrightness= */ PowerManager.BRIGHTNESS_INVALID_FLOAT,
+ /* userSetBrightnessChanged= */ false,
+ /* allowAutoBrightnessWhileDozingConfig= */ false,
+ /* isAutoBrightnessEnabled= */ true);
+ mAutoBrightnessFallbackStrategy.strategySelectionPostProcessor(ssnr);
+
+ verify(mScreenOffBrightnessSensorController).setLightSensorEnabled(true);
+ }
+
+ @Test
+ public void testPostProcess_EnableSensor_PolicyDoze() {
+ boolean isDisplayEnabled = true;
+ int leadDisplayId = NO_LEAD_DISPLAY;
+ mAutoBrightnessFallbackStrategy.setupAutoBrightnessFallbackSensor(mSensorManager,
+ mDisplayDeviceConfig,
+ mHandler, mBrightnessMappingStrategy, isDisplayEnabled, leadDisplayId);
+
+ DisplayManagerInternal.DisplayPowerRequest dpr =
+ new DisplayManagerInternal.DisplayPowerRequest();
+ dpr.policy = POLICY_DOZE;
+ StrategySelectionNotifyRequest ssnr = new StrategySelectionNotifyRequest(dpr,
+ Display.STATE_DOZE, mAutoBrightnessFallbackStrategy,
+ /* lastUserSetScreenBrightness= */ PowerManager.BRIGHTNESS_INVALID_FLOAT,
+ /* userSetBrightnessChanged= */ false,
+ /* allowAutoBrightnessWhileDozingConfig= */ false,
+ /* isAutoBrightnessEnabled= */ true);
+ mAutoBrightnessFallbackStrategy.strategySelectionPostProcessor(ssnr);
+
+ verify(mScreenOffBrightnessSensorController).setLightSensorEnabled(true);
+ }
+
+ @Test
+ public void testPostProcess_DisableSensor_AutoBrightnessDisabled() {
+ boolean isDisplayEnabled = true;
+ int leadDisplayId = NO_LEAD_DISPLAY;
+ mAutoBrightnessFallbackStrategy.setupAutoBrightnessFallbackSensor(mSensorManager,
+ mDisplayDeviceConfig,
+ mHandler, mBrightnessMappingStrategy, isDisplayEnabled, leadDisplayId);
+
+ DisplayManagerInternal.DisplayPowerRequest dpr =
+ new DisplayManagerInternal.DisplayPowerRequest();
+ dpr.policy = POLICY_OFF;
+ StrategySelectionNotifyRequest ssnr = new StrategySelectionNotifyRequest(dpr,
+ Display.STATE_OFF, mAutoBrightnessFallbackStrategy,
+ /* lastUserSetScreenBrightness= */ PowerManager.BRIGHTNESS_INVALID_FLOAT,
+ /* userSetBrightnessChanged= */ false,
+ /* allowAutoBrightnessWhileDozingConfig= */ false,
+ /* isAutoBrightnessEnabled= */ false);
+ mAutoBrightnessFallbackStrategy.strategySelectionPostProcessor(ssnr);
+
+ verify(mScreenOffBrightnessSensorController).setLightSensorEnabled(false);
+ }
+
+ @Test
+ public void testPostProcess_DisableSensor_DisplayDisabled() {
+ boolean isDisplayEnabled = false;
+ int leadDisplayId = NO_LEAD_DISPLAY;
+ mAutoBrightnessFallbackStrategy.setupAutoBrightnessFallbackSensor(mSensorManager,
+ mDisplayDeviceConfig,
+ mHandler, mBrightnessMappingStrategy, isDisplayEnabled, leadDisplayId);
+
+ DisplayManagerInternal.DisplayPowerRequest dpr =
+ new DisplayManagerInternal.DisplayPowerRequest();
+ dpr.policy = POLICY_OFF;
+ StrategySelectionNotifyRequest ssnr = new StrategySelectionNotifyRequest(dpr,
+ Display.STATE_OFF, mAutoBrightnessFallbackStrategy,
+ /* lastUserSetScreenBrightness= */ PowerManager.BRIGHTNESS_INVALID_FLOAT,
+ /* userSetBrightnessChanged= */ false,
+ /* allowAutoBrightnessWhileDozingConfig= */ false,
+ /* isAutoBrightnessEnabled= */ true);
+ mAutoBrightnessFallbackStrategy.strategySelectionPostProcessor(ssnr);
+
+ verify(mScreenOffBrightnessSensorController).setLightSensorEnabled(false);
+ }
+
+ @Test
+ public void testPostProcess_DisableSensor_PolicyBright() {
+ boolean isDisplayEnabled = true;
+ int leadDisplayId = NO_LEAD_DISPLAY;
+ mAutoBrightnessFallbackStrategy.setupAutoBrightnessFallbackSensor(mSensorManager,
+ mDisplayDeviceConfig,
+ mHandler, mBrightnessMappingStrategy, isDisplayEnabled, leadDisplayId);
+
+ DisplayManagerInternal.DisplayPowerRequest dpr =
+ new DisplayManagerInternal.DisplayPowerRequest();
+ dpr.policy = POLICY_BRIGHT;
+ StrategySelectionNotifyRequest ssnr = new StrategySelectionNotifyRequest(dpr,
+ Display.STATE_ON, mAutoBrightnessFallbackStrategy,
+ /* lastUserSetScreenBrightness= */ PowerManager.BRIGHTNESS_INVALID_FLOAT,
+ /* userSetBrightnessChanged= */ false,
+ /* allowAutoBrightnessWhileDozingConfig= */ false,
+ /* isAutoBrightnessEnabled= */ true);
+ mAutoBrightnessFallbackStrategy.strategySelectionPostProcessor(ssnr);
+
+ verify(mScreenOffBrightnessSensorController).setLightSensorEnabled(false);
+ }
+
+ @Test
+ public void testPostProcess_DisableSensor_AutoBrightnessInDoze() {
+ boolean isDisplayEnabled = true;
+ int leadDisplayId = NO_LEAD_DISPLAY;
+ mAutoBrightnessFallbackStrategy.setupAutoBrightnessFallbackSensor(mSensorManager,
+ mDisplayDeviceConfig,
+ mHandler, mBrightnessMappingStrategy, isDisplayEnabled, leadDisplayId);
+
+ DisplayManagerInternal.DisplayPowerRequest dpr =
+ new DisplayManagerInternal.DisplayPowerRequest();
+ dpr.policy = POLICY_DOZE;
+ StrategySelectionNotifyRequest ssnr = new StrategySelectionNotifyRequest(dpr,
+ Display.STATE_DOZE, mAutoBrightnessFallbackStrategy,
+ /* lastUserSetScreenBrightness= */ PowerManager.BRIGHTNESS_INVALID_FLOAT,
+ /* userSetBrightnessChanged= */ false,
+ /* allowAutoBrightnessWhileDozingConfig= */ true,
+ /* isAutoBrightnessEnabled= */ true);
+ mAutoBrightnessFallbackStrategy.strategySelectionPostProcessor(ssnr);
+
+ verify(mScreenOffBrightnessSensorController).setLightSensorEnabled(false);
+ }
+
+ @Test
+ public void testPostProcess_DisableSensor_DisplayIsFollower() {
+ boolean isDisplayEnabled = true;
+ int leadDisplayId = 3;
+ mAutoBrightnessFallbackStrategy.setupAutoBrightnessFallbackSensor(mSensorManager,
+ mDisplayDeviceConfig,
+ mHandler, mBrightnessMappingStrategy, isDisplayEnabled, leadDisplayId);
+
+ DisplayManagerInternal.DisplayPowerRequest dpr =
+ new DisplayManagerInternal.DisplayPowerRequest();
+ dpr.policy = POLICY_OFF;
+ StrategySelectionNotifyRequest ssnr = new StrategySelectionNotifyRequest(dpr,
+ Display.STATE_OFF, mAutoBrightnessFallbackStrategy,
+ /* lastUserSetScreenBrightness= */ PowerManager.BRIGHTNESS_INVALID_FLOAT,
+ /* userSetBrightnessChanged= */ false,
+ /* allowAutoBrightnessWhileDozingConfig= */ false,
+ /* isAutoBrightnessEnabled= */ true);
+ mAutoBrightnessFallbackStrategy.strategySelectionPostProcessor(ssnr);
+
+ verify(mScreenOffBrightnessSensorController).setLightSensorEnabled(false);
+ }
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
index 242d559..62400eb 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
@@ -1088,6 +1088,21 @@
}
@Test
+ public void testModeSwitching_UserSwitch() {
+ DisplayModeDirector director = createDirectorFromFpsRange(0, 90);
+ assertThat(director.getModeSwitchingType()).isEqualTo(
+ DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS);
+
+ int newModeSwitchingType = DisplayManager.SWITCHING_TYPE_NONE;
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.MATCH_CONTENT_FRAME_RATE, newModeSwitchingType);
+ director.onSwitchUser();
+ waitForIdleSync();
+
+ assertThat(director.getModeSwitchingType()).isEqualTo(newModeSwitchingType);
+ }
+
+ @Test
public void testDefaultDisplayModeIsSelectedIfAvailable() {
final float[] refreshRates = new float[]{24f, 25f, 30f, 60f, 90f};
final int defaultModeId = 3;
@@ -1883,6 +1898,62 @@
}
@Test
+ public void testPeakRefreshRate_UserSwitch() {
+ when(mDisplayManagerFlags.isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled())
+ .thenReturn(true);
+ DisplayModeDirector director =
+ new DisplayModeDirector(mContext, mHandler, mInjector,
+ mDisplayManagerFlags, mDisplayDeviceConfigProvider);
+ director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);
+
+ Display.Mode[] modes1 = new Display.Mode[] {
+ new Display.Mode(/* modeId= */ 1, /* width= */ 1280, /* height= */ 720,
+ /* refreshRate= */ 60),
+ new Display.Mode(/* modeId= */ 2, /* width= */ 1280, /* height= */ 720,
+ /* refreshRate= */ 130),
+ };
+ Display.Mode[] modes2 = new Display.Mode[] {
+ new Display.Mode(/* modeId= */ 1, /* width= */ 1280, /* height= */ 720,
+ /* refreshRate= */ 60),
+ new Display.Mode(/* modeId= */ 2, /* width= */ 1280, /* height= */ 720,
+ /* refreshRate= */ 140),
+ };
+ SparseArray<Display.Mode[]> supportedModesByDisplay = new SparseArray<>();
+ supportedModesByDisplay.put(DISPLAY_ID, modes1);
+ supportedModesByDisplay.put(DISPLAY_ID_2, modes2);
+
+ Sensor lightSensor = createLightSensor();
+ SensorManager sensorManager = createMockSensorManager(lightSensor);
+ director.start(sensorManager);
+ director.injectSupportedModesByDisplay(supportedModesByDisplay);
+
+ // Disable Smooth Display
+ setPeakRefreshRate(RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE);
+
+ Vote vote1 = director.getVote(DISPLAY_ID,
+ Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE);
+ Vote vote2 = director.getVote(DISPLAY_ID_2,
+ Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE);
+ assertVoteForRenderFrameRateRange(vote1, /* frameRateLow= */ 0,
+ /* frameRateHigh= */ RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE);
+ assertVoteForRenderFrameRateRange(vote2, /* frameRateLow= */ 0,
+ /* frameRateHigh= */ RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE);
+
+ // Switch user to one that has Smooth Display Enabled
+ Settings.System.putFloat(mContext.getContentResolver(), Settings.System.PEAK_REFRESH_RATE,
+ Float.POSITIVE_INFINITY);
+ director.onSwitchUser();
+ waitForIdleSync();
+
+ vote1 = director.getVote(DISPLAY_ID,
+ Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE);
+ vote2 = director.getVote(DISPLAY_ID_2,
+ Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE);
+ assertVoteForRenderFrameRateRange(vote1, /* frameRateLow= */ 0, /* frameRateHigh= */ 130);
+ assertVoteForRenderFrameRateRange(vote2, /* frameRateLow= */ 0, /* frameRateHigh= */ 140);
+ }
+
+ @Test
@Parameters({
"true, true, 60",
"false, true, 50",
@@ -2036,6 +2107,62 @@
}
@Test
+ public void testMinRefreshRate_UserSwitch() {
+ when(mDisplayManagerFlags.isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled())
+ .thenReturn(true);
+ DisplayModeDirector director =
+ new DisplayModeDirector(mContext, mHandler, mInjector,
+ mDisplayManagerFlags, mDisplayDeviceConfigProvider);
+ director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);
+
+ Display.Mode[] modes1 = new Display.Mode[] {
+ new Display.Mode(/* modeId= */ 1, /* width= */ 1280, /* height= */ 720,
+ /* refreshRate= */ 60),
+ new Display.Mode(/* modeId= */ 2, /* width= */ 1280, /* height= */ 720,
+ /* refreshRate= */ 130),
+ };
+ Display.Mode[] modes2 = new Display.Mode[] {
+ new Display.Mode(/* modeId= */ 1, /* width= */ 1280, /* height= */ 720,
+ /* refreshRate= */ 60),
+ new Display.Mode(/* modeId= */ 2, /* width= */ 1280, /* height= */ 720,
+ /* refreshRate= */ 140),
+ };
+ SparseArray<Display.Mode[]> supportedModesByDisplay = new SparseArray<>();
+ supportedModesByDisplay.put(DISPLAY_ID, modes1);
+ supportedModesByDisplay.put(DISPLAY_ID_2, modes2);
+
+ Sensor lightSensor = createLightSensor();
+ SensorManager sensorManager = createMockSensorManager(lightSensor);
+ director.start(sensorManager);
+ director.injectSupportedModesByDisplay(supportedModesByDisplay);
+
+ // Disable Force Peak Refresh Rate
+ setMinRefreshRate(0);
+
+ Vote vote1 = director.getVote(DISPLAY_ID, Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE);
+ Vote vote2 = director.getVote(DISPLAY_ID_2,
+ Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE);
+ assertVoteForRenderFrameRateRange(vote1, /* frameRateLow= */ 0,
+ /* frameRateHigh= */ Float.POSITIVE_INFINITY);
+ assertVoteForRenderFrameRateRange(vote2, /* frameRateLow= */ 0,
+ /* frameRateHigh= */ Float.POSITIVE_INFINITY);
+
+ // Switch user to one that has Force Peak Refresh Rate enabled
+ Settings.System.putFloat(mContext.getContentResolver(), Settings.System.MIN_REFRESH_RATE,
+ Float.POSITIVE_INFINITY);
+ director.onSwitchUser();
+ waitForIdleSync();
+
+ vote1 = director.getVote(DISPLAY_ID, Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE);
+ vote2 = director.getVote(DISPLAY_ID_2,
+ Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE);
+ assertVoteForRenderFrameRateRange(vote1, /* frameRateLow= */ 130,
+ /* frameRateHigh= */ Float.POSITIVE_INFINITY);
+ assertVoteForRenderFrameRateRange(vote2, /* frameRateLow= */ 140,
+ /* frameRateHigh= */ Float.POSITIVE_INFINITY);
+ }
+
+ @Test
public void testPeakAndMinRefreshRate_FlagEnabled_DisplayWithOneMode() {
when(mDisplayManagerFlags.isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled())
.thenReturn(true);
diff --git a/services/tests/mockingservicestests/jni/Android.bp b/services/tests/mockingservicestests/jni/Android.bp
index 1eb9888..00543a8 100644
--- a/services/tests/mockingservicestests/jni/Android.bp
+++ b/services/tests/mockingservicestests/jni/Android.bp
@@ -21,6 +21,7 @@
srcs: [
":lib_cachedAppOptimizer_native",
+ ":lib_freezer_native",
":lib_gameManagerService_native",
":lib_oomConnection_native",
"onload.cpp",
diff --git a/services/tests/mockingservicestests/jni/onload.cpp b/services/tests/mockingservicestests/jni/onload.cpp
index fb91051..cb246d1 100644
--- a/services/tests/mockingservicestests/jni/onload.cpp
+++ b/services/tests/mockingservicestests/jni/onload.cpp
@@ -25,6 +25,7 @@
namespace android {
int register_android_server_am_CachedAppOptimizer(JNIEnv* env);
+int register_android_server_am_Freezer(JNIEnv* env);
int register_android_server_app_GameManagerService(JNIEnv* env);
int register_android_server_am_OomConnection(JNIEnv* env);
};
@@ -42,8 +43,8 @@
}
ALOG_ASSERT(env, "Could not retrieve the env!");
register_android_server_am_CachedAppOptimizer(env);
+ register_android_server_am_Freezer(env);
register_android_server_app_GameManagerService(env);
register_android_server_am_OomConnection(env);
return JNI_VERSION_1_4;
}
-
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index cb15d6f..b980ca0 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -132,6 +132,7 @@
import android.content.Intent;
import android.content.PermissionChecker;
import android.content.pm.PackageManagerInternal;
+import android.content.pm.UserInfo;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Bundle;
@@ -149,6 +150,7 @@
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.os.UserManager;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
@@ -176,6 +178,7 @@
import com.android.server.LocalServices;
import com.android.server.SystemClockTime.TimeConfidence;
import com.android.server.SystemService;
+import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.permission.PermissionManagerService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.pm.pkg.AndroidPackage;
@@ -250,6 +253,8 @@
@Mock
private ActivityManagerInternal mActivityManagerInternal;
@Mock
+ private UserManagerInternal mUserManagerInternal;
+ @Mock
private ActivityManager mActivityManager;
@Mock
private PackageManagerInternal mPackageManagerInternal;
@@ -447,6 +452,8 @@
() -> LocalServices.getService(PermissionManagerServiceInternal.class));
doReturn(mActivityManagerInternal).when(
() -> LocalServices.getService(ActivityManagerInternal.class));
+ doReturn(mUserManagerInternal).when(
+ () -> LocalServices.getService(UserManagerInternal.class));
doReturn(mPackageManagerInternal).when(
() -> LocalServices.getService(PackageManagerInternal.class));
doReturn(mAppStateTracker).when(() -> LocalServices.getService(AppStateTracker.class));
@@ -1252,6 +1259,26 @@
}
@Test
+ public void wakeupShouldBeScheduledForFullUsers_skipsGuestSystemAndProfiles() {
+ final int systemUserId = 0;
+ final int fullUserId = 10;
+ final int privateProfileId = 12;
+ final int guestUserId = 13;
+ when(mUserManagerInternal.getUserInfo(fullUserId)).thenReturn(new UserInfo(fullUserId,
+ "TestUser2", UserInfo.FLAG_FULL));
+ when(mUserManagerInternal.getUserInfo(privateProfileId)).thenReturn(new UserInfo(
+ privateProfileId, "TestUser3", UserInfo.FLAG_PROFILE));
+ when(mUserManagerInternal.getUserInfo(guestUserId)).thenReturn(new UserInfo(
+ guestUserId, "TestUserGuest", null, 0, UserManager.USER_TYPE_FULL_GUEST));
+ when(mUserManagerInternal.getUserInfo(systemUserId)).thenReturn(new UserInfo(
+ systemUserId, "TestUserSystem", null, 0, UserManager.USER_TYPE_FULL_SYSTEM));
+ assertTrue(mService.shouldAddWakeupForUser(fullUserId));
+ assertFalse(mService.shouldAddWakeupForUser(systemUserId));
+ assertFalse(mService.shouldAddWakeupForUser(privateProfileId));
+ assertFalse(mService.shouldAddWakeupForUser(guestUserId));
+ }
+
+ @Test
public void sendsTimeTickOnInteractive() {
final ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
// Stubbing so the handler doesn't actually run the runnable.
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/UserWakeupStoreTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/UserWakeupStoreTest.java
index 5bd919f..72883e2 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/UserWakeupStoreTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/UserWakeupStoreTest.java
@@ -23,7 +23,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import static org.testng.AssertJUnit.assertFalse;
import android.os.Environment;
import android.os.FileUtils;
@@ -52,7 +51,6 @@
private static final int USER_ID_1 = 10;
private static final int USER_ID_2 = 11;
private static final int USER_ID_3 = 12;
- private static final int USER_ID_SYSTEM = 0;
private static final long TEST_TIMESTAMP = 150_000;
private static final File TEST_SYSTEM_DIR = new File(InstrumentationRegistry
.getInstrumentation().getContext().getDataDir(), "alarmsTestDir");
@@ -112,14 +110,6 @@
}
@Test
- public void testAddWakeupForSystemUser_shouldDoNothing() {
- mUserWakeupStore.addUserWakeup(USER_ID_SYSTEM, TEST_TIMESTAMP - 19_000);
- assertEquals(0, mUserWakeupStore.getUserIdsToWakeup(TEST_TIMESTAMP).length);
- final File file = new File(ROOT_DIR , "usersWithAlarmClocks.xml");
- assertFalse(file.exists());
- }
-
- @Test
public void testAddMultipleWakeupsForUser_ensureOnlyLastWakeupRemains() {
final long finalAlarmTime = TEST_TIMESTAMP - 13_000;
mUserWakeupStore.addUserWakeup(USER_ID_1, TEST_TIMESTAMP - 29_000);
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
index 03439e55..d203de5 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
@@ -21,10 +21,21 @@
import static com.android.server.am.ActivityManagerService.Injector;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import android.app.ActivityManagerInternal;
+import android.app.ActivityManagerInternal.FrozenProcessListener;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -33,12 +44,14 @@
import android.os.HandlerThread;
import android.os.MessageQueue;
import android.os.Process;
+import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.provider.DeviceConfig;
import android.text.TextUtils;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.internal.annotations.GuardedBy;
import com.android.modules.utils.testing.ExtendedMockitoRule;
import com.android.modules.utils.testing.TestableDeviceConfig;
import com.android.server.LocalServices;
@@ -55,9 +68,11 @@
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
/**
@@ -79,12 +94,17 @@
private CountDownLatch mCountDown;
private ActivityManagerService mAms;
private Context mContext;
+ private TestFreezer mFreezer;
+ private CountDownLatch mFreezeCounter;
private TestInjector mInjector;
private TestProcessDependencies mProcessDependencies;
@Mock
private PackageManagerInternal mPackageManagerInt;
+ // Control whether the freezer mock reports that freezing is enabled or not.
+ private boolean mUseFreezer;
+
@Rule
public final ApplicationExitInfoTest.ServiceThreadRule
mServiceThreadRule = new ApplicationExitInfoTest.ServiceThreadRule();
@@ -103,9 +123,12 @@
true /* allowIo */);
mThread.start();
mContext = InstrumentationRegistry.getInstrumentation().getContext();
+
+ mUseFreezer = false;
+ mFreezer = new TestFreezer();
+
mInjector = new TestInjector(mContext);
- mAms = new ActivityManagerService(
- new TestInjector(mContext), mServiceThreadRule.getThread());
+ mAms = new ActivityManagerService(mInjector, mServiceThreadRule.getThread());
doReturn(new ComponentName("", "")).when(mPackageManagerInt).getSystemUiServiceComponent();
mProcessDependencies = new TestProcessDependencies();
mCachedAppOptimizerUnderTest = new CachedAppOptimizer(mAms,
@@ -126,6 +149,7 @@
mHandlerThread.quit();
mThread.quit();
mCountDown = null;
+ mFreezeCounter = null;
}
private ProcessRecord makeProcessRecord(int pid, int uid, int packageUid, String processName,
@@ -179,7 +203,7 @@
assertThat(mCachedAppOptimizerUnderTest.mProcStateThrottle)
.containsExactlyElementsIn(expected);
- Assume.assumeTrue(mCachedAppOptimizerUnderTest.isFreezerSupported());
+ Assume.assumeTrue(mAms.isAppFreezerSupported());
assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isEqualTo(
CachedAppOptimizer.DEFAULT_USE_FREEZER);
}
@@ -265,8 +289,8 @@
CachedAppOptimizer.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB + 1);
assertThat(mCachedAppOptimizerUnderTest.mProcStateThrottle).containsExactly(1, 2, 3);
- Assume.assumeTrue(CachedAppOptimizer.isFreezerSupported());
- if (CachedAppOptimizer.isFreezerSupported()) {
+ Assume.assumeTrue(mAms.isAppFreezerSupported());
+ if (mAms.isAppFreezerSupported()) {
if (CachedAppOptimizer.DEFAULT_USE_FREEZER) {
assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isFalse();
} else {
@@ -300,7 +324,7 @@
@Test
public void useFreeze_doesNotListenToDeviceConfigChanges() throws InterruptedException {
- Assume.assumeTrue(CachedAppOptimizer.isFreezerSupported());
+ Assume.assumeTrue(mAms.isAppFreezerSupported());
assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isFalse();
@@ -353,7 +377,7 @@
@Test
public void useFreeze_listensToDeviceConfigChangesBadValues() throws InterruptedException {
- Assume.assumeTrue(CachedAppOptimizer.isFreezerSupported());
+ Assume.assumeTrue(mAms.isAppFreezerSupported());
assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isFalse();
// When we push an invalid flag value...
@@ -982,6 +1006,87 @@
}
}
+ @Test
+ public void testFreezerDelegator() throws Exception {
+ mUseFreezer = true;
+ mProcessDependencies.setRss(new long[] {
+ 0 /*total_rss*/,
+ 0 /*file*/,
+ 0 /*anon*/,
+ 0 /*swap*/,
+ 0 /*shmem*/
+ });
+
+ // Force the system to use the freezer
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
+ CachedAppOptimizer.KEY_USE_FREEZER, "true", false);
+ mCachedAppOptimizerUnderTest.init();
+ initActivityManagerService();
+
+ assertTrue(mAms.isAppFreezerSupported());
+ assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isTrue();
+
+ int pid = 10000;
+ int uid = 2;
+ int pkgUid = 3;
+ ProcessRecord app = makeProcessRecord(pid, uid, pkgUid, "p1", "app1");
+
+ mFreezeCounter = new CountDownLatch(1);
+ mCachedAppOptimizerUnderTest.forceFreezeForTest(app, true);
+ assertTrue(mFreezeCounter.await(5, TimeUnit.SECONDS));
+
+ mFreezeCounter = new CountDownLatch(1);
+ mCachedAppOptimizerUnderTest.forceFreezeForTest(app, false);
+ assertTrue(mFreezeCounter.await(5, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void testFrozenNotifier() throws Exception {
+ mUseFreezer = true;
+ mProcessDependencies.setRss(new long[] {
+ 0 /*total_rss*/,
+ 0 /*file*/,
+ 0 /*anon*/,
+ 0 /*swap*/,
+ 0 /*shmem*/
+ });
+
+ // Force the system to use the freezer
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
+ CachedAppOptimizer.KEY_USE_FREEZER, "true", false);
+ mCachedAppOptimizerUnderTest.init();
+ initActivityManagerService();
+
+ assertTrue(mAms.isAppFreezerSupported());
+ assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isTrue();
+
+ int pid = 10000;
+ int uid = 2;
+ int pkgUid = 3;
+ ProcessRecord app = makeProcessRecord(pid, uid, pkgUid, "p1", "app1");
+ assertNotNull(app.mOptRecord);
+
+ FrozenProcessListener listener = new FrozenProcessListener() {
+ @Override
+ public void onProcessFrozen(int pid) {
+ mFreezeCounter.countDown();
+ }
+ @Override
+ public void onProcessUnfrozen(int pid) {
+ mFreezeCounter.countDown();
+ }
+ };
+ mCachedAppOptimizerUnderTest.addFrozenProcessListener(app, directExecutor(), listener);
+
+ mFreezeCounter = new CountDownLatch(2);
+ mCachedAppOptimizerUnderTest.forceFreezeForTest(app, true);
+ assertTrue(mFreezeCounter.await(5, TimeUnit.SECONDS));
+
+ mFreezeCounter = new CountDownLatch(2);
+ mCachedAppOptimizerUnderTest.forceFreezeForTest(app, false);
+ assertTrue(mFreezeCounter.await(5, TimeUnit.SECONDS));
+ }
+
private void setFlag(String key, String value, boolean defaultValue) throws Exception {
mCountDown = new CountDownLatch(1);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, key, value, defaultValue);
@@ -1042,6 +1147,11 @@
public Handler getUiHandler(ActivityManagerService service) {
return mHandler;
}
+
+ @Override
+ public Freezer getFreezer() {
+ return mFreezer;
+ }
}
// Test implementation for ProcessDependencies.
@@ -1069,4 +1179,27 @@
mRssAfterCompaction = newValues;
}
}
+
+ // Intercept Freezer calls.
+ private class TestFreezer extends Freezer {
+ @Override
+ public void setProcessFrozen(int pid, int uid, boolean frozen) {
+ mFreezeCounter.countDown();
+ }
+
+ @Override
+ public int freezeBinder(int pid, boolean freeze, int timeoutMs) {
+ return 0;
+ }
+
+ @Override
+ public int getBinderFreezeInfo(int pid) {
+ return 0;
+ }
+
+ @Override
+ public boolean isFreezerSupported() {
+ return mUseFreezer;
+ }
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/OWNERS b/services/tests/mockingservicestests/src/com/android/server/am/OWNERS
index 2cbc226..4fac647 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/OWNERS
+++ b/services/tests/mockingservicestests/src/com/android/server/am/OWNERS
@@ -1,3 +1,4 @@
include /services/core/java/com/android/server/am/OWNERS
per-file ApplicationStartInfoTest.java = yforta@google.com, carmenjackson@google.com, jji@google.com
+per-file CachedAppOptimizerTest.java = file:/PERFORMANCE_OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ProcessObserverTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ProcessObserverTest.java
index 3572d23..014b98c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ProcessObserverTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ProcessObserverTest.java
@@ -56,6 +56,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
@@ -238,6 +239,7 @@
/**
* Verify that a process start event is dispatched to process observers.
*/
+ @Ignore("b/323959187")
@Test
public void testNormal() throws Exception {
ProcessRecord app = startProcess();
diff --git a/services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java b/services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java
index ce2bb95..d45e312 100644
--- a/services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java
+++ b/services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java
@@ -44,6 +44,7 @@
import android.os.RemoteException;
import android.os.VibrationAttributes;
import android.os.Vibrator;
+import android.os.WorkSource;
import android.os.test.TestLooper;
import android.provider.Settings;
import android.testing.TestableContext;
@@ -60,6 +61,7 @@
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.concurrent.Executor;
@@ -231,7 +233,7 @@
}
@Test
- public void testOnWakeLockListener_RemoteException_NoRethrow() {
+ public void testOnWakeLockListener_RemoteException_NoRethrow() throws RemoteException {
when(mPowerManagerFlags.improveWakelockLatency()).thenReturn(true);
createNotifier();
clearInvocations(mWakeLockLog, mBatteryStats, mAppOpsManager);
@@ -249,33 +251,58 @@
verifyZeroInteractions(mWakeLockLog);
mTestLooper.dispatchAll();
verify(mWakeLockLog).onWakeLockReleased("wakelockTag", uid, 1);
-
+ clearInvocations(mBatteryStats);
mNotifier.onWakeLockAcquired(PowerManager.PARTIAL_WAKE_LOCK, "wakelockTag",
"my.package.name", uid, pid, /* workSource= */ null, /* historyTag= */ null,
exceptingCallback);
- mNotifier.onWakeLockChanging(PowerManager.PARTIAL_WAKE_LOCK, "wakelockTag",
- "my.package.name", uid, pid, /* workSource= */ null, /* historyTag= */ null,
- exceptingCallback,
- PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "wakelockTag",
- "my.package.name", uid, pid, /* newWorkSource= */ null, /* newHistoryTag= */ null,
- exceptingCallback);
- verifyNoMoreInteractions(mWakeLockLog);
+
+ verifyNoMoreInteractions(mWakeLockLog, mBatteryStats);
mTestLooper.dispatchAll();
verify(mWakeLockLog).onWakeLockAcquired("wakelockTag", uid,
PowerManager.PARTIAL_WAKE_LOCK, 1);
+ verify(mBatteryStats).noteStartWakelock(uid, pid, "wakelockTag", /* historyTag= */ null,
+ BatteryStats.WAKE_TYPE_PARTIAL, false);
+
+ verifyNoMoreInteractions(mWakeLockLog, mBatteryStats);
+ WorkSource worksourceOld = Mockito.mock(WorkSource.class);
+ WorkSource worksourceNew = Mockito.mock(WorkSource.class);
+
+ mNotifier.onWakeLockChanging(PowerManager.PARTIAL_WAKE_LOCK, "wakelockTag",
+ "my.package.name", uid, pid, worksourceOld, /* historyTag= */ null,
+ exceptingCallback,
+ PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "wakelockTag",
+ "my.package.name", uid, pid, worksourceNew, /* newHistoryTag= */ null,
+ exceptingCallback);
+ mTestLooper.dispatchAll();
+ verify(mBatteryStats).noteChangeWakelockFromSource(worksourceOld, pid, "wakelockTag",
+ null, BatteryStats.WAKE_TYPE_PARTIAL, worksourceNew, pid, "wakelockTag",
+ null, BatteryStats.WAKE_TYPE_FULL, false);
// If we didn't throw, we're good!
// Test with improveWakelockLatency flag false, hence the wakelock log will run on the same
// thread
- clearInvocations(mWakeLockLog);
+ clearInvocations(mWakeLockLog, mBatteryStats);
when(mPowerManagerFlags.improveWakelockLatency()).thenReturn(false);
+ // Acquire the wakelock
mNotifier.onWakeLockAcquired(PowerManager.PARTIAL_WAKE_LOCK, "wakelockTag",
"my.package.name", uid, pid, /* workSource= */ null, /* historyTag= */ null,
exceptingCallback);
verify(mWakeLockLog).onWakeLockAcquired("wakelockTag", uid,
PowerManager.PARTIAL_WAKE_LOCK, -1);
+ // Update the wakelock
+ mNotifier.onWakeLockChanging(PowerManager.PARTIAL_WAKE_LOCK, "wakelockTag",
+ "my.package.name", uid, pid, worksourceOld, /* historyTag= */ null,
+ exceptingCallback,
+ PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "wakelockTag",
+ "my.package.name", uid, pid, worksourceNew, /* newHistoryTag= */ null,
+ exceptingCallback);
+ verify(mBatteryStats).noteChangeWakelockFromSource(worksourceOld, pid, "wakelockTag",
+ null, BatteryStats.WAKE_TYPE_PARTIAL, worksourceNew, pid, "wakelockTag",
+ null, BatteryStats.WAKE_TYPE_FULL, false);
+
+ // Release the wakelock
mNotifier.onWakeLockReleased(PowerManager.PARTIAL_WAKE_LOCK, "wakelockTag",
"my.package.name", uid, pid, /* workSource= */ null, /* historyTag= */ null,
exceptingCallback);
diff --git a/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java
index b737e0f..40c521a 100644
--- a/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -1304,6 +1304,7 @@
.setDozeOverrideFromDreamManager(
Display.STATE_ON,
Display.STATE_REASON_DEFAULT_POLICY,
+ PowerManager.BRIGHTNESS_INVALID_FLOAT,
PowerManager.BRIGHTNESS_DEFAULT);
assertTrue(isAcquired[0]);
}
diff --git a/services/tests/servicestests/jni/Android.bp b/services/tests/servicestests/jni/Android.bp
index c30e4eb..0a31037 100644
--- a/services/tests/servicestests/jni/Android.bp
+++ b/services/tests/servicestests/jni/Android.bp
@@ -21,6 +21,7 @@
srcs: [
":lib_cachedAppOptimizer_native",
+ ":lib_freezer_native",
":lib_gameManagerService_native",
":lib_oomConnection_native",
":lib_anrTimer_native",
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
index 7b71f85..1426d5d 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
@@ -48,6 +48,7 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
+import android.content.res.Resources;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region;
@@ -67,6 +68,7 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.R;
import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.LocalServices;
@@ -118,6 +120,7 @@
final FullScreenMagnificationController.ControllerContext mMockControllerCtx =
mock(FullScreenMagnificationController.ControllerContext.class);
final Context mMockContext = mock(Context.class);
+ final Resources mMockResources = mock(Resources.class);
final AccessibilityTraceManager mMockTraceManager = mock(AccessibilityTraceManager.class);
final WindowManagerInternal mMockWindowManager = mock(WindowManagerInternal.class);
private final MagnificationAnimationCallback mAnimationCallback = mock(
@@ -162,6 +165,7 @@
mResolver = new MockContentResolver();
mResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
when(mMockContext.getContentResolver()).thenReturn(mResolver);
+ when(mMockContext.getResources()).thenReturn(mMockResources);
mOriginalMagnificationPersistedScale = Settings.Secure.getFloatForUser(mResolver,
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, 2.0f,
CURRENT_USER_ID);
@@ -928,7 +932,8 @@
/* displayId= */ i,
/* isMagnifierActivated= */ true,
/* isAlwaysOnEnabled= */ false,
- /* expectedActivated= */ false);
+ /* expectedActivated= */ false,
+ /* expectedMagnified= */ false);
resetMockWindowManager();
}
}
@@ -940,7 +945,24 @@
/* displayId= */ i,
/* isMagnifierActivated= */ true,
/* isAlwaysOnEnabled= */ true,
- /* expectedActivated= */ true);
+ /* expectedActivated= */ true,
+ /* expectedMagnified= */ false);
+ resetMockWindowManager();
+ }
+ }
+
+ @Test
+ public void testUserContextChange_magnifierActivatedAndKeepMagnifiedEnabled_stayActivated() {
+ when(mMockResources.getBoolean(
+ R.bool.config_magnification_keep_zoom_level_when_context_changed))
+ .thenReturn(true);
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ contextChange_expectedValues(
+ /* displayId= */ i,
+ /* isMagnifierActivated= */ true,
+ /* isAlwaysOnEnabled= */ true,
+ /* expectedActivated= */ true,
+ /* expectedMagnified= */ true);
resetMockWindowManager();
}
}
@@ -952,7 +974,8 @@
/* displayId= */ i,
/* isMagnifierActivated= */ false,
/* isAlwaysOnEnabled= */ false,
- /* expectedActivated= */ false);
+ /* expectedActivated= */ false,
+ /* expectedMagnified= */ false);
resetMockWindowManager();
}
}
@@ -964,14 +987,15 @@
/* displayId= */ i,
/* isMagnifierActivated= */ false,
/* isAlwaysOnEnabled= */ true,
- /* expectedActivated= */ false);
+ /* expectedActivated= */ false,
+ /* expectedMagnified= */ false);
resetMockWindowManager();
}
}
private void contextChange_expectedValues(
int displayId, boolean isMagnifierActivated, boolean isAlwaysOnEnabled,
- boolean expectedActivated) {
+ boolean expectedActivated, boolean expectedMagnified) {
mFullScreenMagnificationController.setAlwaysOnMagnificationEnabled(isAlwaysOnEnabled);
register(displayId);
MagnificationCallbacks callbacks = getMagnificationCallbacks(displayId);
@@ -982,7 +1006,7 @@
callbacks.onUserContextChanged();
mMessageCapturingHandler.sendAllMessages();
checkActivatedAndMagnifying(
- /* activated= */ expectedActivated, /* magnifying= */ false, displayId);
+ /* activated= */ expectedActivated, expectedMagnified, displayId);
if (expectedActivated) {
verify(mMockThumbnail, times(2)).setThumbnailBounds(
@@ -1526,8 +1550,8 @@
private void checkActivatedAndMagnifying(boolean activated, boolean magnifying, int displayId) {
final boolean isActivated = mFullScreenMagnificationController.isActivated(displayId);
final boolean isMagnifying = mFullScreenMagnificationController.getScale(displayId) > 1.0f;
- assertTrue(isActivated == activated);
- assertTrue(isMagnifying == magnifying);
+ assertEquals(isActivated, activated);
+ assertEquals(isMagnifying, magnifying);
}
private MagnificationCallbacks getMagnificationCallbacks(int displayId) {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
index 60bcecc..957ee06 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
@@ -17,6 +17,7 @@
package com.android.server.accessibility.magnification;
import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_HOVER_MOVE;
import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_POINTER_DOWN;
import static android.view.MotionEvent.ACTION_POINTER_INDEX_SHIFT;
@@ -27,6 +28,8 @@
import static com.android.server.testutils.TestUtils.strictMock;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -300,7 +303,8 @@
mMockFullScreenMagnificationVibrationHelper,
mMockMagnificationLogger,
ViewConfiguration.get(mContext),
- mMockOneFingerPanningSettingsProvider);
+ mMockOneFingerPanningSettingsProvider,
+ new MouseEventHandler(mFullScreenMagnificationController));
// OverscrollHandler is only supported on watches.
// @See config_enable_a11y_fullscreen_magnification_overscroll_handler
if (isWatch()) {
@@ -1398,6 +1402,302 @@
mFullScreenMagnificationController.reset(DISPLAY_0, /* animate= */ false);
}
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE)
+ public void testMouseMoveEventsDoNotMoveMagnifierViewport() {
+ runMoveEventsDoNotMoveMagnifierViewport(InputDevice.SOURCE_MOUSE);
+ }
+
+ @Test
+ public void testStylusMoveEventsDoNotMoveMagnifierViewport() {
+ runMoveEventsDoNotMoveMagnifierViewport(InputDevice.SOURCE_STYLUS);
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE)
+ public void testMouseHoverMoveEventsDoNotMoveMagnifierViewport() {
+ runHoverMoveEventsDoNotMoveMagnifierViewport(InputDevice.SOURCE_MOUSE);
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE)
+ public void testStylusHoverMoveEventsDoNotMoveMagnifierViewport() {
+ runHoverMoveEventsDoNotMoveMagnifierViewport(InputDevice.SOURCE_STYLUS);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE)
+ public void testMouseHoverMoveEventsMoveMagnifierViewport() {
+ runHoverMovesViewportTest(InputDevice.SOURCE_MOUSE);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE)
+ public void testStylusHoverMoveEventsMoveMagnifierViewport() {
+ runHoverMovesViewportTest(InputDevice.SOURCE_STYLUS);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE)
+ public void testMouseDownEventsDoNotMoveMagnifierViewport() {
+ runDownDoesNotMoveViewportTest(InputDevice.SOURCE_MOUSE);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE)
+ public void testStylusDownEventsDoNotMoveMagnifierViewport() {
+ runDownDoesNotMoveViewportTest(InputDevice.SOURCE_STYLUS);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE)
+ public void testMouseUpEventsDoNotMoveMagnifierViewport() {
+ runUpDoesNotMoveViewportTest(InputDevice.SOURCE_MOUSE);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE)
+ public void testStylusUpEventsDoNotMoveMagnifierViewport() {
+ runUpDoesNotMoveViewportTest(InputDevice.SOURCE_STYLUS);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE)
+ public void testMouseMoveEventsMoveMagnifierViewport() {
+ final EventCaptor eventCaptor = new EventCaptor();
+ mMgh.setNext(eventCaptor);
+
+ float centerX =
+ (INITIAL_MAGNIFICATION_BOUNDS.left + INITIAL_MAGNIFICATION_BOUNDS.width()) / 2.0f;
+ float centerY =
+ (INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
+ float scale = 6.2f; // value is unimportant but unique among tests to increase coverage.
+ mFullScreenMagnificationController.setScaleAndCenter(
+ DISPLAY_0, centerX, centerY, scale, /* animate= */ false, 1);
+ MotionEvent event = mouseEvent(centerX, centerY, ACTION_HOVER_MOVE);
+ send(event, InputDevice.SOURCE_MOUSE);
+ fastForward(20);
+ event = mouseEvent(centerX, centerY, ACTION_DOWN);
+ send(event, InputDevice.SOURCE_MOUSE);
+ fastForward(20);
+
+ // Mouse drag event does impact magnifier viewport.
+ event = mouseEvent(centerX + 30, centerY + 60, ACTION_MOVE);
+ send(event, InputDevice.SOURCE_MOUSE);
+ fastForward(20);
+
+ assertThat(mFullScreenMagnificationController.getCenterX(DISPLAY_0))
+ .isEqualTo(centerX + 30);
+ assertThat(mFullScreenMagnificationController.getCenterY(DISPLAY_0))
+ .isEqualTo(centerY + 60);
+
+ // The mouse events were not consumed by magnifier.
+ assertThat(eventCaptor.mEvents.size()).isEqualTo(3);
+ assertThat(eventCaptor.mEvents.get(0).getSource()).isEqualTo(InputDevice.SOURCE_MOUSE);
+ assertThat(eventCaptor.mEvents.get(1).getSource()).isEqualTo(InputDevice.SOURCE_MOUSE);
+ assertThat(eventCaptor.mEvents.get(2).getSource()).isEqualTo(InputDevice.SOURCE_MOUSE);
+
+ final List<Integer> expectedActions = new ArrayList();
+ expectedActions.add(Integer.valueOf(ACTION_HOVER_MOVE));
+ expectedActions.add(Integer.valueOf(ACTION_DOWN));
+ expectedActions.add(Integer.valueOf(ACTION_MOVE));
+ assertActionsInOrder(eventCaptor.mEvents, expectedActions);
+ }
+
+ private void runHoverMovesViewportTest(int source) {
+ final EventCaptor eventCaptor = new EventCaptor();
+ mMgh.setNext(eventCaptor);
+
+ float centerX =
+ (INITIAL_MAGNIFICATION_BOUNDS.left + INITIAL_MAGNIFICATION_BOUNDS.width()) / 2.0f;
+ float centerY =
+ (INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
+ float scale = 4.0f; // value is unimportant but unique among tests to increase coverage.
+ mFullScreenMagnificationController.setScaleAndCenter(
+ DISPLAY_0, centerX, centerY, scale, /* animate= */ false, 1);
+
+ // HOVER_MOVE should change magnifier viewport.
+ MotionEvent event = motionEvent(centerX + 20, centerY, ACTION_HOVER_MOVE);
+ send(event, source);
+ fastForward(20);
+
+ assertThat(mFullScreenMagnificationController.getCenterX(DISPLAY_0))
+ .isEqualTo(centerX + 20);
+ assertThat(mFullScreenMagnificationController.getCenterY(DISPLAY_0)).isEqualTo(centerY);
+
+ // Make sure mouse events are sent onward and not blocked after moving the viewport.
+ assertThat(eventCaptor.mEvents.size()).isEqualTo(1);
+ assertThat(eventCaptor.mEvents.get(0).getSource()).isEqualTo(source);
+
+ // Send another hover.
+ event = motionEvent(centerX + 20, centerY + 40, ACTION_HOVER_MOVE);
+ send(event, source);
+ fastForward(20);
+
+ assertThat(mFullScreenMagnificationController.getCenterX(DISPLAY_0))
+ .isEqualTo(centerX + 20);
+ assertThat(mFullScreenMagnificationController.getCenterY(DISPLAY_0))
+ .isEqualTo(centerY + 40);
+
+ assertThat(eventCaptor.mEvents.size()).isEqualTo(2);
+ assertThat(eventCaptor.mEvents.get(1).getSource()).isEqualTo(source);
+
+ final List<Integer> expectedActions = new ArrayList();
+ expectedActions.add(Integer.valueOf(ACTION_HOVER_MOVE));
+ expectedActions.add(Integer.valueOf(ACTION_HOVER_MOVE));
+ assertActionsInOrder(eventCaptor.mEvents, expectedActions);
+ }
+
+ private void runDownDoesNotMoveViewportTest(int source) {
+ final EventCaptor eventCaptor = new EventCaptor();
+ mMgh.setNext(eventCaptor);
+
+ float centerX =
+ (INITIAL_MAGNIFICATION_BOUNDS.left + INITIAL_MAGNIFICATION_BOUNDS.width()) / 2.0f;
+ float centerY =
+ (INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
+ float scale = 5.3f; // value is unimportant but unique among tests to increase coverage.
+ mFullScreenMagnificationController.setScaleAndCenter(
+ DISPLAY_0, centerX, centerY, scale, /* animate= */ false, 1);
+ MotionEvent event = motionEvent(centerX, centerY, ACTION_HOVER_MOVE);
+ send(event, source);
+ fastForward(20);
+
+ // Down event doesn't impact magnifier viewport.
+ event = motionEvent(centerX + 20, centerY + 40, ACTION_DOWN);
+ send(event, source);
+ fastForward(20);
+
+ assertThat(mFullScreenMagnificationController.getCenterX(DISPLAY_0)).isEqualTo(centerX);
+ assertThat(mFullScreenMagnificationController.getCenterY(DISPLAY_0)).isEqualTo(centerY);
+
+ // The events were not consumed by magnifier.
+ assertThat(eventCaptor.mEvents.size()).isEqualTo(2);
+ assertThat(eventCaptor.mEvents.get(0).getSource()).isEqualTo(source);
+ assertThat(eventCaptor.mEvents.get(1).getSource()).isEqualTo(source);
+
+ final List<Integer> expectedActions = new ArrayList();
+ expectedActions.add(Integer.valueOf(ACTION_HOVER_MOVE));
+ expectedActions.add(Integer.valueOf(ACTION_DOWN));
+ assertActionsInOrder(eventCaptor.mEvents, expectedActions);
+ }
+
+ private void runUpDoesNotMoveViewportTest(int source) {
+ final EventCaptor eventCaptor = new EventCaptor();
+ mMgh.setNext(eventCaptor);
+
+ float centerX =
+ (INITIAL_MAGNIFICATION_BOUNDS.left + INITIAL_MAGNIFICATION_BOUNDS.width()) / 2.0f;
+ float centerY =
+ (INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
+ float scale = 2.7f; // value is unimportant but unique among tests to increase coverage.
+ mFullScreenMagnificationController.setScaleAndCenter(
+ DISPLAY_0, centerX, centerY, scale, /* animate= */ false, 1);
+ MotionEvent event = motionEvent(centerX, centerY, ACTION_HOVER_MOVE);
+ send(event, source);
+ fastForward(20);
+ event = motionEvent(centerX, centerY, ACTION_DOWN);
+ send(event, source);
+ fastForward(20);
+
+ // Up event should not move the viewport.
+ event = motionEvent(centerX + 30, centerY + 60, ACTION_UP);
+ send(event, source);
+ fastForward(20);
+
+ // The events were not consumed by magnifier.
+ assertThat(eventCaptor.mEvents.size()).isEqualTo(3);
+ assertThat(eventCaptor.mEvents.get(0).getSource()).isEqualTo(source);
+ assertThat(eventCaptor.mEvents.get(1).getSource()).isEqualTo(source);
+ assertThat(eventCaptor.mEvents.get(2).getSource()).isEqualTo(source);
+
+ final List<Integer> expectedActions = new ArrayList();
+ expectedActions.add(Integer.valueOf(ACTION_HOVER_MOVE));
+ expectedActions.add(Integer.valueOf(ACTION_DOWN));
+ expectedActions.add(Integer.valueOf(ACTION_UP));
+ assertActionsInOrder(eventCaptor.mEvents, expectedActions);
+ }
+
+ private void runMoveEventsDoNotMoveMagnifierViewport(int source) {
+ final EventCaptor eventCaptor = new EventCaptor();
+ mMgh.setNext(eventCaptor);
+
+ float centerX =
+ (INITIAL_MAGNIFICATION_BOUNDS.left + INITIAL_MAGNIFICATION_BOUNDS.width()) / 2.0f;
+ float centerY =
+ (INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
+ float scale = 3.8f; // value is unimportant but unique among tests to increase coverage.
+ mFullScreenMagnificationController.setScaleAndCenter(
+ DISPLAY_0, centerX, centerY, scale, /* animate= */ false, 1);
+ centerX = mFullScreenMagnificationController.getCenterX(DISPLAY_0);
+ centerY = mFullScreenMagnificationController.getCenterY(DISPLAY_0);
+
+ MotionEvent event = motionEvent(centerX, centerY, ACTION_DOWN);
+ send(event, source);
+ fastForward(20);
+
+ // Drag event doesn't impact magnifier viewport.
+ event = stylusEvent(centerX + 18, centerY + 42, ACTION_MOVE);
+ send(event, source);
+ fastForward(20);
+
+ assertThat(mFullScreenMagnificationController.getCenterX(DISPLAY_0)).isEqualTo(centerX);
+ assertThat(mFullScreenMagnificationController.getCenterY(DISPLAY_0)).isEqualTo(centerY);
+
+ // The events were not consumed by magnifier.
+ assertThat(eventCaptor.mEvents.size()).isEqualTo(2);
+ assertThat(eventCaptor.mEvents.get(0).getSource()).isEqualTo(source);
+ assertThat(eventCaptor.mEvents.get(1).getSource()).isEqualTo(source);
+
+ final List<Integer> expectedActions = new ArrayList();
+ expectedActions.add(Integer.valueOf(ACTION_DOWN));
+ expectedActions.add(Integer.valueOf(ACTION_MOVE));
+ assertActionsInOrder(eventCaptor.mEvents, expectedActions);
+ }
+
+ private void runHoverMoveEventsDoNotMoveMagnifierViewport(int source) {
+ final EventCaptor eventCaptor = new EventCaptor();
+ mMgh.setNext(eventCaptor);
+
+ float centerX =
+ (INITIAL_MAGNIFICATION_BOUNDS.left + INITIAL_MAGNIFICATION_BOUNDS.width()) / 2.0f;
+ float centerY =
+ (INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
+ float scale = 4.0f; // value is unimportant but unique among tests to increase coverage.
+ mFullScreenMagnificationController.setScaleAndCenter(
+ DISPLAY_0, centerX, centerY, scale, /* animate= */ false, 1);
+ centerX = mFullScreenMagnificationController.getCenterX(DISPLAY_0);
+ centerY = mFullScreenMagnificationController.getCenterY(DISPLAY_0);
+
+ // HOVER_MOVE should not change magnifier viewport.
+ MotionEvent event = motionEvent(centerX + 20, centerY, ACTION_HOVER_MOVE);
+ send(event, source);
+ fastForward(20);
+
+ assertThat(mFullScreenMagnificationController.getCenterX(DISPLAY_0)).isEqualTo(centerX);
+ assertThat(mFullScreenMagnificationController.getCenterY(DISPLAY_0)).isEqualTo(centerY);
+
+ // Make sure events are sent onward and not blocked after moving the viewport.
+ assertThat(eventCaptor.mEvents.size()).isEqualTo(1);
+ assertThat(eventCaptor.mEvents.get(0).getSource()).isEqualTo(source);
+
+ // Send another hover.
+ event = motionEvent(centerX + 20, centerY + 40, ACTION_HOVER_MOVE);
+ send(event, source);
+ fastForward(20);
+
+ assertThat(mFullScreenMagnificationController.getCenterX(DISPLAY_0)).isEqualTo(centerX);
+ assertThat(mFullScreenMagnificationController.getCenterY(DISPLAY_0)).isEqualTo(centerY);
+
+ assertThat(eventCaptor.mEvents.size()).isEqualTo(2);
+ assertThat(eventCaptor.mEvents.get(1).getSource()).isEqualTo(source);
+
+ final List<Integer> expectedActions = new ArrayList();
+ expectedActions.add(Integer.valueOf(ACTION_HOVER_MOVE));
+ expectedActions.add(Integer.valueOf(ACTION_HOVER_MOVE));
+ assertActionsInOrder(eventCaptor.mEvents, expectedActions);
+ }
+
private void enableOneFingerPanning(boolean enable) {
mMockOneFingerPanningEnabled = enable;
when(mMockOneFingerPanningSettingsProvider.isOneFingerPanningEnabled()).thenReturn(enable);
@@ -1795,8 +2095,14 @@
mMgh.notifyShortcutTriggered();
}
+ /** Sends the MotionEvent from a Touchscreen source */
private void send(MotionEvent event) {
- event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+ send(event, InputDevice.SOURCE_TOUCHSCREEN);
+ }
+
+ /** Sends the MotionEvent from the given source type. */
+ private void send(MotionEvent event, int source) {
+ event.setSource(source);
try {
mMgh.onMotionEvent(event, event, /* policyFlags */ 0);
} catch (Throwable t) {
@@ -1810,9 +2116,30 @@
return ev;
}
+ private static MotionEvent fromMouse(MotionEvent ev) {
+ ev.setSource(InputDevice.SOURCE_MOUSE);
+ return ev;
+ }
+
+ private static MotionEvent fromStylus(MotionEvent ev) {
+ ev.setSource(InputDevice.SOURCE_STYLUS);
+ return ev;
+ }
+
+ private MotionEvent motionEvent(float x, float y, int action) {
+ return MotionEvent.obtain(mLastDownTime, mClock.now(), action, x, y, 0);
+ }
+
+ private MotionEvent mouseEvent(float x, float y, int action) {
+ return fromMouse(motionEvent(x, y, action));
+ }
+
+ private MotionEvent stylusEvent(float x, float y, int action) {
+ return fromStylus(motionEvent(x, y, action));
+ }
+
private MotionEvent moveEvent(float x, float y) {
- return fromTouchscreen(
- MotionEvent.obtain(mLastDownTime, mClock.now(), ACTION_MOVE, x, y, 0));
+ return fromTouchscreen(motionEvent(x, y, ACTION_MOVE));
}
private MotionEvent downEvent() {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
index c99e040..31e15de 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
@@ -341,7 +341,8 @@
twoFingerTap();
twoFingerTap();
// Wait for two-finger tap gesture completed.
- SystemClock.sleep(ViewConfiguration.getDoubleTapMinTime() + 500);
+ SystemClock.sleep(MagnificationGestureMatcher
+ .getMagnificationMultiTapTimeout(mContext) + 100);
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
break;
@@ -403,7 +404,8 @@
twoFingerTap();
twoFingerTap();
// Wait for two-finger tap gesture completed.
- SystemClock.sleep(ViewConfiguration.getDoubleTapMinTime() + 500);
+ SystemClock.sleep(MagnificationGestureMatcher
+ .getMagnificationMultiTapTimeout(mContext) + 100);
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
break;
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
index 2d4dbb7..78c9372 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
@@ -479,6 +479,15 @@
eq(mContext.getOpPackageName()), anyInt(), anyInt(), any());
}
+ @Test
+ public void testCancelAuth_whenClientWaitingForCookie() throws RemoteException {
+ final FaceAuthenticationClient client = createClient(true);
+ client.waitForCookie(mCallback);
+ client.cancel();
+
+ verify(mCallback).onClientFinished(client, false);
+ }
+
private FaceAuthenticationClient createClient() throws RemoteException {
return createClient(2 /* version */, mClientMonitorCallbackConverter,
false /* allowBackgroundAuthentication */, true /* isBiometricPrompt */,
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
index 6ec888c..7e1d421 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
@@ -117,7 +117,6 @@
private static final int TOUCH_Y = 20;
private static final float TOUCH_MAJOR = 4.4f;
private static final float TOUCH_MINOR = 5.5f;
- private static final int FINGER_UP = 111;
@Rule
public final TestableContext mContext = new TestableContext(
@@ -383,6 +382,8 @@
@Test
public void subscribeContextAndStartHal() throws RemoteException {
+ when(mHal.authenticateWithContext(anyLong(), any())).thenReturn(mCancellationSignal);
+
final FingerprintAuthenticationClient client = createClient();
client.start(mCallback);
@@ -691,6 +692,17 @@
verify(mLockoutTracker).addFailedAttemptForUser(USER_ID);
}
+ @Test
+ public void testCancelAuth_whenClientWaitingForCookie() throws RemoteException {
+ final FingerprintAuthenticationClient client = createClientWithoutBackgroundAuth();
+ client.waitForCookie(mCallback);
+ client.cancel();
+ mLooper.moveTimeForward(10);
+ mLooper.dispatchAll();
+
+ verify(mCallback).onClientFinished(client, false);
+ }
+
private FingerprintAuthenticationClient createClient() throws RemoteException {
return createClient(100 /* version */, true /* allowBackgroundAuthentication */,
true /* isBiometricPrompt */,
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java
index a34e796..242880c 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java
@@ -178,7 +178,7 @@
}
@Test
- @RequiresFlagsEnabled(Flags.FLAG_NOTIFY_FINGERPRINT_LOE)
+ @RequiresFlagsEnabled(Flags.FLAG_NOTIFY_FINGERPRINTS_LOE)
public void invalidBiometricUserState() throws Exception {
mClient = createClient();
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/GenericWindowPolicyControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/GenericWindowPolicyControllerTest.java
index e078238..9317d06 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/GenericWindowPolicyControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/GenericWindowPolicyControllerTest.java
@@ -42,9 +42,11 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentSender;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.net.Uri;
+import android.os.Binder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
@@ -518,19 +520,6 @@
}
@Test
- public void canActivityBeLaunched_permissionComponent_isBlocked() {
- GenericWindowPolicyController gwpc = createGwpcWithPermissionComponent(BLOCKED_COMPONENT);
- gwpc.setDisplayId(DISPLAY_ID, /* isMirrorDisplay= */ false);
-
- ActivityInfo activityInfo = getActivityInfo(
- BLOCKED_PACKAGE_NAME,
- BLOCKED_PACKAGE_NAME,
- /* displayOnRemoteDevices */ true,
- /* targetDisplayCategory */ null);
- assertActivityIsBlocked(gwpc, activityInfo);
- }
-
- @Test
public void registerRunningAppsChangedListener_onRunningAppsChanged_listenersNotified() {
ArraySet<Integer> uids = new ArraySet<>(Arrays.asList(TEST_UID));
GenericWindowPolicyController gwpc = createGwpc();
@@ -605,13 +594,15 @@
// register interceptor and intercept intent
when(mIntentListenerCallback.shouldInterceptIntent(any(Intent.class))).thenReturn(true);
assertThat(gwpc.canActivityBeLaunched(activityInfo, intent,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID, /*isNewTask=*/false))
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID, /* isNewTask= */false,
+ /* isResultExpected = */ false, /* intentSender= */ null))
.isFalse();
// unregister interceptor and launch activity
when(mIntentListenerCallback.shouldInterceptIntent(any(Intent.class))).thenReturn(false);
assertThat(gwpc.canActivityBeLaunched(activityInfo, intent,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID, /*isNewTask=*/false))
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID, /* isNewTask= */false,
+ /* isResultExpected = */ false, /* intentSender= */ null))
.isTrue();
}
@@ -630,13 +621,36 @@
// register interceptor with different filter
when(mIntentListenerCallback.shouldInterceptIntent(any(Intent.class))).thenReturn(false);
assertThat(gwpc.canActivityBeLaunched(activityInfo, intent,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID, /*isNewTask=*/false))
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID, /* isNewTask= */false,
+ /* isResultExpected = */ false, /* intentSender= */ null))
.isTrue();
verify(mIntentListenerCallback, timeout(TIMEOUT_MILLIS))
.shouldInterceptIntent(any(Intent.class));
}
@Test
+ public void canActivityBeLaunched_resultExpected_noIntentSenderInCallback() {
+ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("testing"));
+
+ GenericWindowPolicyController gwpc = createGwpc();
+ gwpc.setDisplayId(DISPLAY_ID, /* isMirrorDisplay= */ false);
+ ActivityInfo activityInfo = getActivityInfo(
+ NONBLOCKED_APP_PACKAGE_NAME,
+ NONBLOCKED_APP_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ false,
+ /* targetDisplayCategory */ null);
+
+ IntentSender intentSender = new IntentSender(new Binder());
+ assertThat(gwpc.canActivityBeLaunched(activityInfo, intent,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID, /* isNewTask= */false,
+ /* isResultExpected = */ true, /* intentSender= */ () -> intentSender))
+ .isFalse();
+
+ verify(mActivityBlockedCallback, timeout(TIMEOUT_MILLIS))
+ .onActivityBlocked(DISPLAY_ID, activityInfo, /* intentSender= */ null);
+ }
+
+ @Test
public void onTopActivitychanged_null_noCallback() {
GenericWindowPolicyController gwpc = createGwpc();
gwpc.setDisplayId(DISPLAY_ID, /* isMirrorDisplay= */ false);
@@ -672,7 +686,8 @@
verify(mSecureWindowCallback, after(TIMEOUT_MILLIS).never())
.onSecureWindowShown(DISPLAY_ID, activityInfo.applicationInfo.uid);
- verify(mActivityBlockedCallback, never()).onActivityBlocked(DISPLAY_ID, activityInfo);
+ verify(mActivityBlockedCallback, never())
+ .onActivityBlocked(eq(DISPLAY_ID), eq(activityInfo), any());
}
@Test
@@ -691,7 +706,7 @@
verify(mSecureWindowCallback, timeout(TIMEOUT_MILLIS)).onSecureWindowShown(DISPLAY_ID,
activityInfo.applicationInfo.uid);
verify(mActivityBlockedCallback, after(TIMEOUT_MILLIS).never())
- .onActivityBlocked(DISPLAY_ID, activityInfo);
+ .onActivityBlocked(eq(DISPLAY_ID), eq(activityInfo), any());
}
@Test
@@ -710,7 +725,8 @@
verify(mSecureWindowCallback, after(TIMEOUT_MILLIS).never())
.onSecureWindowShown(DISPLAY_ID, activityInfo.applicationInfo.uid);
- verify(mActivityBlockedCallback, never()).onActivityBlocked(DISPLAY_ID, activityInfo);
+ verify(mActivityBlockedCallback, never())
+ .onActivityBlocked(eq(DISPLAY_ID), eq(activityInfo), any());
}
@Test
@@ -740,7 +756,6 @@
/* activityPolicyExemptions= */ new ArraySet<>(),
/* crossTaskNavigationAllowedByDefault= */ true,
/* crossTaskNavigationExemptions= */ new ArraySet<>(),
- /* permissionDialogComponent= */ null,
/* activityListener= */ mActivityListener,
/* activityBlockedCallback= */ mActivityBlockedCallback,
/* secureWindowCallback= */ mSecureWindowCallback,
@@ -760,7 +775,6 @@
/* activityPolicyExemptions= */ new ArraySet<>(),
/* crossTaskNavigationAllowedByDefault= */ true,
/* crossTaskNavigationExemptions= */ new ArraySet<>(),
- /* permissionDialogComponent= */ null,
/* activityListener= */ mActivityListener,
/* activityBlockedCallback= */ mActivityBlockedCallback,
/* secureWindowCallback= */ mSecureWindowCallback,
@@ -781,7 +795,6 @@
/* activityPolicyExemptions= */ new ArraySet<>(),
/* crossTaskNavigationAllowedByDefault= */ true,
/* crossTaskNavigationExemptions= */ new ArraySet<>(),
- /* permissionDialogComponent= */ null,
/* activityListener= */ mActivityListener,
/* activityBlockedCallback= */ mActivityBlockedCallback,
/* secureWindowCallback= */ null,
@@ -802,7 +815,6 @@
/* activityPolicyExemptions= */ Collections.singleton(blockedComponent),
/* crossTaskNavigationAllowedByDefault= */ true,
/* crossTaskNavigationExemptions= */ new ArraySet<>(),
- /* permissionDialogComponent= */ null,
/* activityListener= */ mActivityListener,
/* activityBlockedCallback= */ mActivityBlockedCallback,
/* secureWindowCallback= */ null,
@@ -823,7 +835,6 @@
/* activityPolicyExemptions= */ Collections.singleton(allowedComponent),
/* crossTaskNavigationAllowedByDefault= */ true,
/* crossTaskNavigationExemptions= */ new ArraySet<>(),
- /* permissionDialogComponent= */ null,
/* activityListener= */ mActivityListener,
/* activityBlockedCallback= */ mActivityBlockedCallback,
/* secureWindowCallback= */ null,
@@ -844,7 +855,6 @@
/* activityPolicyExemptions= */ new ArraySet<>(),
/* crossTaskNavigationAllowedByDefault= */ true,
/* crossTaskNavigationExemptions= */ new ArraySet<>(),
- /* permissionDialogComponent= */ null,
/* activityListener= */ mActivityListener,
/* activityBlockedCallback= */ mActivityBlockedCallback,
/* secureWindowCallback= */ null,
@@ -865,7 +875,6 @@
/* activityPolicyExemptions= */ new ArraySet<>(),
/* crossTaskNavigationAllowedByDefault= */ true,
/* crossTaskNavigationExemptions= */ Collections.singleton(blockedComponent),
- /* permissionDialogComponent= */ null,
/* activityListener= */ mActivityListener,
/* activityBlockedCallback= */ mActivityBlockedCallback,
/* secureWindowCallback= */ null,
@@ -886,29 +895,6 @@
/* activityPolicyExemptions= */ new ArraySet<>(),
/* crossTaskNavigationAllowedByDefault= */ false,
/* crossTaskNavigationExemptions= */ Collections.singleton(allowedComponent),
- /* permissionDialogComponent= */ null,
- /* activityListener= */ mActivityListener,
- /* activityBlockedCallback= */ mActivityBlockedCallback,
- /* secureWindowCallback= */ null,
- /* intentListenerCallback= */ mIntentListenerCallback,
- /* displayCategories= */ new ArraySet<>(),
- /* showTasksInHostDeviceRecents= */ true,
- /* customHomeComponent= */ null);
- }
-
- private GenericWindowPolicyController createGwpcWithPermissionComponent(
- ComponentName permissionComponent) {
- //TODO instert the component
- return new GenericWindowPolicyController(
- 0,
- 0,
- AttributionSource.myAttributionSource(),
- /* allowedUsers= */ new ArraySet<>(getCurrentUserId()),
- /* activityLaunchAllowedByDefault= */ true,
- /* activityPolicyExemptions= */ new ArraySet<>(),
- /* crossTaskNavigationAllowedByDefault= */ false,
- /* crossTaskNavigationExemptions= */ new ArraySet<>(),
- /* permissionDialogComponent= */ permissionComponent,
/* activityListener= */ mActivityListener,
/* activityBlockedCallback= */ mActivityBlockedCallback,
/* secureWindowCallback= */ null,
@@ -954,11 +940,12 @@
private void assertActivityCanBeLaunched(GenericWindowPolicyController gwpc, int fromDisplay,
boolean isNewTask, int windowingMode, ActivityInfo activityInfo) {
+ IntentSender intentSender = new IntentSender(new Binder());
assertThat(gwpc.canActivityBeLaunched(activityInfo, null, windowingMode, fromDisplay,
- isNewTask)).isTrue();
+ isNewTask, /* isResultExpected= */ false, () -> intentSender)).isTrue();
verify(mActivityBlockedCallback, after(TIMEOUT_MILLIS).never())
- .onActivityBlocked(fromDisplay, activityInfo);
+ .onActivityBlocked(fromDisplay, activityInfo, intentSender);
verify(mIntentListenerCallback, never()).shouldInterceptIntent(any(Intent.class));
}
@@ -970,23 +957,26 @@
private void assertActivityIsBlocked(GenericWindowPolicyController gwpc, int fromDisplay,
boolean isNewTask, int windowingMode, ActivityInfo activityInfo) {
+ IntentSender intentSender = new IntentSender(new Binder());
assertThat(gwpc.canActivityBeLaunched(activityInfo, null, windowingMode, fromDisplay,
- isNewTask)).isFalse();
+ isNewTask, /* isResultExpected= */ false, () -> intentSender)).isFalse();
verify(mActivityBlockedCallback, timeout(TIMEOUT_MILLIS))
- .onActivityBlocked(fromDisplay, activityInfo);
+ .onActivityBlocked(fromDisplay, activityInfo, intentSender);
verify(mIntentListenerCallback, after(TIMEOUT_MILLIS).never())
.shouldInterceptIntent(any(Intent.class));
}
private void assertNoActivityLaunched(GenericWindowPolicyController gwpc, int fromDisplay,
ActivityInfo activityInfo) {
+ IntentSender intentSender = new IntentSender(new Binder());
assertThat(gwpc.canActivityBeLaunched(activityInfo, null,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID, true))
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID, /* isNewTask= */false,
+ /* isResultExpected= */ false, () -> intentSender))
.isFalse();
verify(mActivityBlockedCallback, after(TIMEOUT_MILLIS).never())
- .onActivityBlocked(fromDisplay, activityInfo);
+ .onActivityBlocked(eq(fromDisplay), eq(activityInfo), any());
verify(mIntentListenerCallback, never()).shouldInterceptIntent(any(Intent.class));
}
}
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
index da8961d..c288212 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
@@ -314,7 +314,8 @@
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfo, mAssociationInfo.getDisplayName());
gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false);
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /* isNewTask= */ false,
+ /* isResultExpected = */ false, /* intentSender= */ null);
return blockedAppIntent;
}
@@ -1522,7 +1523,8 @@
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfo, mAssociationInfo.getDisplayName());
gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false);
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /* isNewTask= */ false,
+ /* isResultExpected = */ false, /* intentSender= */ null);
verify(mContext, never()).startActivityAsUser(argThat(intent ->
intent.filterEquals(blockedAppIntent)), any(), any());
@@ -1543,15 +1545,15 @@
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfo, mAssociationInfo.getDisplayName());
gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false);
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /* isNewTask= */ false,
+ /* isResultExpected = */ false, /* intentSender= */ null);
verify(mContext).startActivityAsUser(argThat(intent ->
intent.filterEquals(blockedAppIntent)), any(), any());
}
@Test
- public void openPermissionControllerOnVirtualDisplay_displayOnRemoteDevices_startsWhenFlagIsEnabled() {
- mSetFlagsRule.enableFlags(Flags.FLAG_STREAM_PERMISSIONS);
+ public void openPermissionControllerOnVirtualDisplay_displayOnRemoteDevices_starts() {
addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
DISPLAY_ID_1);
@@ -1565,15 +1567,15 @@
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfo, mAssociationInfo.getDisplayName());
gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false);
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /* isNewTask= */ false,
+ /* isResultExpected = */ false, /* intentSender= */ null);
verify(mContext, never()).startActivityAsUser(argThat(intent ->
intent.filterEquals(blockedAppIntent)), any(), any());
}
@Test
- public void openPermissionControllerOnVirtualDisplay_dontDisplayOnRemoteDevices_startsWhenFlagIsEnabled() {
- mSetFlagsRule.enableFlags(Flags.FLAG_STREAM_PERMISSIONS);
+ public void openPermissionControllerOnVirtualDisplay_dontDisplayOnRemoteDevices_starts() {
addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
DISPLAY_ID_1);
@@ -1587,7 +1589,8 @@
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfo, mAssociationInfo.getDisplayName());
gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false);
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /* isNewTask= */ false,
+ /* isResultExpected = */ false, /* intentSender= */ null);
verify(mContext).startActivityAsUser(argThat(intent ->
intent.filterEquals(blockedAppIntent)), any(), any());
@@ -1608,7 +1611,8 @@
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfo, mAssociationInfo.getDisplayName());
gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false);
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /* isNewTask= */ false,
+ /* isResultExpected = */ false, /* intentSender= */ null);
verify(mContext).startActivityAsUser(argThat(intent ->
intent.filterEquals(blockedAppIntent)), any(), any());
@@ -1629,7 +1633,8 @@
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfo, mAssociationInfo.getDisplayName());
gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false);
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /* isNewTask= */ false,
+ /* isResultExpected = */ false, /* intentSender= */ null);
verify(mContext).startActivityAsUser(argThat(intent ->
intent.filterEquals(blockedAppIntent)), any(), any());
@@ -1650,7 +1655,8 @@
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfo, mAssociationInfo.getDisplayName());
gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false);
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /* isNewTask= */ false,
+ /* isResultExpected = */ false, /* intentSender= */ null);
verify(mContext).startActivityAsUser(argThat(intent ->
intent.filterEquals(blockedAppIntent)), any(), any());
@@ -1671,7 +1677,8 @@
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfo, mAssociationInfo.getDisplayName());
gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false);
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /* isNewTask= */ false,
+ /* isResultExpected = */ false, /* intentSender= */ null);
verify(mContext).startActivityAsUser(argThat(intent ->
intent.filterEquals(blockedAppIntent)), any(), any());
@@ -1693,7 +1700,8 @@
/* displayOnRemoteDevices */ true,
/* targetDisplayCategory */ null);
assertThat(gwpc.canActivityBeLaunched(activityInfo, null,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/ false))
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /* isNewTask= */ false,
+ /* isResultExpected = */ false, /* intentSender= */ null))
.isFalse();
// Verify that BlockedAppStreamingActivity also doesn't launch for mirror displays.
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
@@ -1718,7 +1726,8 @@
/* displayOnRemoteDevices */ true,
/* targetDisplayCategory */ null);
assertThat(gwpc.canActivityBeLaunched(activityInfo, null,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/ false))
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /* isNewTask= */ false,
+ /* isResultExpected = */ false, /* intentSender= */ null))
.isTrue();
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfo, mAssociationInfo.getDisplayName());
@@ -1755,35 +1764,7 @@
}
@Test
- public void canActivityBeLaunched_permissionDialog_flagDisabled_isBlocked() {
- mSetFlagsRule.disableFlags(Flags.FLAG_STREAM_PERMISSIONS);
- VirtualDeviceParams params = new VirtualDeviceParams.Builder().build();
- mDeviceImpl.close();
- mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params);
- doNothing().when(mContext).startActivityAsUser(any(), any(), any());
-
- addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
- GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
- DISPLAY_ID_1);
- ComponentName permissionComponent = getPermissionDialogComponent();
- ActivityInfo activityInfo = getActivityInfo(
- permissionComponent.getPackageName(),
- permissionComponent.getClassName(),
- /* displayOnRemoteDevices */ true,
- /* targetDisplayCategory */ null);
- assertThat(gwpc.canActivityBeLaunched(activityInfo, null,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false))
- .isFalse();
-
- Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
- activityInfo, mAssociationInfo.getDisplayName());
- verify(mContext).startActivityAsUser(argThat(intent ->
- intent.filterEquals(blockedAppIntent)), any(), any());
- }
-
- @Test
- public void canActivityBeLaunched_permissionDialog_flagEnabled_isStreamed() {
- mSetFlagsRule.enableFlags(Flags.FLAG_STREAM_PERMISSIONS);
+ public void canActivityBeLaunched_permissionDialog_isStreamed() {
VirtualDeviceParams params = new VirtualDeviceParams.Builder().build();
mDeviceImpl.close();
mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params);
@@ -1798,7 +1779,8 @@
/* displayOnRemoteDevices */ true,
/* targetDisplayCategory */ null);
assertThat(gwpc.canActivityBeLaunched(activityInfo, null,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false))
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /* isNewTask= */ false,
+ /* isResultExpected = */ false, /* intentSender= */ null))
.isTrue();
}
@@ -1814,7 +1796,8 @@
/* displayOnRemoteDevices */ true,
/* targetDisplayCategory */ null);
assertThat(gwpc.canActivityBeLaunched(activityInfo, intent,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false))
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /* isNewTask= */ false,
+ /* isResultExpected = */ false, /* intentSender= */ null))
.isTrue();
}
@@ -1845,7 +1828,8 @@
// register interceptor and intercept intent
mDeviceImpl.registerIntentInterceptor(interceptor, intentFilter);
assertThat(gwpc.canActivityBeLaunched(activityInfo, intent,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false))
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /* isNewTask= */ false,
+ /* isResultExpected = */ false, /* intentSender= */ null))
.isFalse();
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(interceptor).onIntentIntercepted(intentCaptor.capture());
@@ -1857,7 +1841,8 @@
// unregister interceptor and launch activity
mDeviceImpl.unregisterIntentInterceptor(interceptor);
assertThat(gwpc.canActivityBeLaunched(activityInfo, intent,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false))
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /* isNewTask= */ false,
+ /* isResultExpected = */ false, /* intentSender= */ null))
.isTrue();
}
@@ -1888,7 +1873,8 @@
mDeviceImpl.registerIntentInterceptor(interceptor, intentFilter);
assertThat(gwpc.canActivityBeLaunched(activityInfo, intent,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false))
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /* isNewTask= */ false,
+ /* isResultExpected = */ false, /* intentSender= */ null))
.isTrue();
}
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
index b946a43..c3db396 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
@@ -85,7 +85,6 @@
/* activityPolicyExemptions= */ new ArraySet<>(),
/* crossTaskNavigationAllowedByDefault= */ true,
/* crossTaskNavigationExemptions= */ new ArraySet<>(),
- /* permissionDialogComponent */ null,
/* activityListener= */ null,
/* activityBlockedCallback= */ null,
/* secureWindowCallback= */ null,
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java
index 599a3b8..4f7f381 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java
@@ -270,6 +270,36 @@
}
@Test
+ public void cecDevices_tracking_event_update_device() {
+ int logicalAddress = Constants.ADDR_PLAYBACK_1;
+ int initialPhysicalAddress = 0x1000;
+ int type = HdmiDeviceInfo.DEVICE_PLAYBACK;
+ String osdName = "Test Device";
+
+ mHdmiCecNetwork.handleCecMessage(
+ HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(logicalAddress,
+ initialPhysicalAddress, type));
+ // Change OSD to make the info different
+ mHdmiCecNetwork.handleCecMessage(
+ HdmiCecMessageBuilder.buildSetOsdNameCommand(logicalAddress,
+ Constants.ADDR_BROADCAST, osdName));
+ synchronized (mHdmiCecNetwork.mLock) {
+ assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1);
+ }
+
+ HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress);
+ assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
+ assertThat(cecDeviceInfo.getPhysicalAddress()).isEqualTo(initialPhysicalAddress);
+ assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(type);
+
+ // ADD for physical address first detected
+ // UPDATE for updating device with new OSD name
+ assertThat(mDeviceEventListenerStatuses).containsExactly(
+ HdmiControlManager.DEVICE_EVENT_ADD_DEVICE,
+ HdmiControlManager.DEVICE_EVENT_UPDATE_DEVICE);
+ }
+
+ @Test
public void cecDevices_tracking_updateDeviceInfo_sameDoesntNotify() {
int logicalAddress = Constants.ADDR_PLAYBACK_1;
int physicalAddress = 0x1000;
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java
index e06d939..de70280 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java
@@ -2454,6 +2454,50 @@
}
@Test
+ public void testBeepVolume_politeNotif_Avalanche_exemptCategories() throws Exception {
+ mSetFlagsRule.enableFlags(Flags.FLAG_POLITE_NOTIFICATIONS);
+ mSetFlagsRule.enableFlags(Flags.FLAG_CROSS_APP_POLITE_NOTIFICATIONS);
+ mSetFlagsRule.enableFlags(Flags.FLAG_POLITE_NOTIFICATIONS_ATTN_UPDATE);
+ TestableFlagResolver flagResolver = new TestableFlagResolver();
+ flagResolver.setFlagOverride(NotificationFlags.NOTIF_VOLUME1, 50);
+ flagResolver.setFlagOverride(NotificationFlags.NOTIF_VOLUME2, 0);
+ initAttentionHelper(flagResolver);
+
+ // Trigger avalanche trigger intent
+ final Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ intent.putExtra("state", false);
+ mAvalancheBroadcastReceiver.onReceive(getContext(), intent);
+
+ // CATEGORY_ALARM is exempted
+ NotificationRecord r = getBeepyNotification();
+ r.getNotification().category = Notification.CATEGORY_ALARM;
+ // Should beep at 100% volume
+ mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS);
+ verifyBeepVolume(1.0f);
+ assertNotEquals(-1, r.getLastAudiblyAlertedMs());
+
+ // CATEGORY_CAR_EMERGENCY is exempted
+ Mockito.reset(mRingtonePlayer);
+ NotificationRecord r2 = getBeepyNotification();
+ r2.getNotification().category = Notification.CATEGORY_CAR_EMERGENCY;
+ // Should beep at 100% volume
+ mAttentionHelper.buzzBeepBlinkLocked(r2, DEFAULT_SIGNALS);
+ verifyBeepVolume(1.0f);
+ assertNotEquals(-1, r2.getLastAudiblyAlertedMs());
+
+ // CATEGORY_CAR_WARNING is exempted
+ Mockito.reset(mRingtonePlayer);
+ NotificationRecord r3 = getBeepyNotification();
+ r3.getNotification().category = Notification.CATEGORY_CAR_WARNING;
+ // Should beep at 100% volume
+ mAttentionHelper.buzzBeepBlinkLocked(r3, DEFAULT_SIGNALS);
+ verifyBeepVolume(1.0f);
+ assertNotEquals(-1, r3.getLastAudiblyAlertedMs());
+
+ verify(mAccessibilityService, times(3)).sendAccessibilityEvent(any(), anyInt());
+ }
+
+ @Test
public void testBeepVolume_politeNotif_exemptEmergency() throws Exception {
mSetFlagsRule.enableFlags(Flags.FLAG_POLITE_NOTIFICATIONS);
mSetFlagsRule.disableFlags(Flags.FLAG_CROSS_APP_POLITE_NOTIFICATIONS);
@@ -2492,6 +2536,73 @@
}
@Test
+ public void testBeepVolume_politeNotif_exemptCategories() throws Exception {
+ mSetFlagsRule.enableFlags(Flags.FLAG_POLITE_NOTIFICATIONS);
+ mSetFlagsRule.disableFlags(Flags.FLAG_CROSS_APP_POLITE_NOTIFICATIONS);
+ mSetFlagsRule.enableFlags(Flags.FLAG_POLITE_NOTIFICATIONS_ATTN_UPDATE);
+ TestableFlagResolver flagResolver = new TestableFlagResolver();
+ flagResolver.setFlagOverride(NotificationFlags.NOTIF_VOLUME1, 50);
+ flagResolver.setFlagOverride(NotificationFlags.NOTIF_VOLUME2, 0);
+ // NOTIFICATION_COOLDOWN_ALL setting is enabled
+ Settings.System.putInt(getContext().getContentResolver(),
+ Settings.System.NOTIFICATION_COOLDOWN_ALL, 1);
+ initAttentionHelper(flagResolver);
+
+ // CATEGORY_ALARM is exempted
+ NotificationRecord r = getBeepyNotification();
+ r.getNotification().category = Notification.CATEGORY_ALARM;
+ mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS);
+ Mockito.reset(mRingtonePlayer);
+
+ // update should beep at 100% volume
+ mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS);
+ assertNotEquals(-1, r.getLastAudiblyAlertedMs());
+ verifyBeepVolume(1.0f);
+
+ // 2nd update should beep at 100% volume
+ Mockito.reset(mRingtonePlayer);
+ mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS);
+ assertNotEquals(-1, r.getLastAudiblyAlertedMs());
+ verifyBeepVolume(1.0f);
+
+ // CATEGORY_CAR_WARNING is exempted
+ r = getBeepyNotification();
+ r.getNotification().category = Notification.CATEGORY_CAR_WARNING;
+ mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS);
+ Mockito.reset(mRingtonePlayer);
+
+ // update should beep at 100% volume
+ mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS);
+ assertNotEquals(-1, r.getLastAudiblyAlertedMs());
+ verifyBeepVolume(1.0f);
+
+ // 2nd update should beep at 100% volume
+ Mockito.reset(mRingtonePlayer);
+ mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS);
+ assertNotEquals(-1, r.getLastAudiblyAlertedMs());
+ verifyBeepVolume(1.0f);
+
+ // CATEGORY_CAR_EMERGENCY is exempted
+ r = getBeepyNotification();
+ r.getNotification().category = Notification.CATEGORY_CAR_EMERGENCY;
+ mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS);
+ Mockito.reset(mRingtonePlayer);
+
+ // update should beep at 100% volume
+ mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS);
+ assertNotEquals(-1, r.getLastAudiblyAlertedMs());
+ verifyBeepVolume(1.0f);
+
+ // 2nd update should beep at 100% volume
+ Mockito.reset(mRingtonePlayer);
+ mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS);
+ assertNotEquals(-1, r.getLastAudiblyAlertedMs());
+ verifyBeepVolume(1.0f);
+
+ verify(mAccessibilityService, times(9)).sendAccessibilityEvent(any(), anyInt());
+ }
+
+ @Test
public void testBeepVolume_politeNotif_applyPerApp() throws Exception {
mSetFlagsRule.enableFlags(Flags.FLAG_POLITE_NOTIFICATIONS);
mSetFlagsRule.disableFlags(Flags.FLAG_CROSS_APP_POLITE_NOTIFICATIONS);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
index f7340ab..3c3c2f3 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
@@ -19,12 +19,18 @@
import static android.app.AutomaticZenRule.TYPE_BEDTIME;
import static android.app.Flags.FLAG_MODES_UI;
import static android.app.Flags.modesUi;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
+import static android.app.NotificationManager.Policy.suppressedEffectsToString;
import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
import static android.provider.Settings.Global.ZEN_MODE_OFF;
import static android.service.notification.Condition.SOURCE_UNKNOWN;
import static android.service.notification.Condition.SOURCE_USER_ACTION;
import static android.service.notification.Condition.STATE_FALSE;
import static android.service.notification.Condition.STATE_TRUE;
+import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_ON;
import static android.service.notification.ZenPolicy.CONVERSATION_SENDERS_IMPORTANT;
import static android.service.notification.ZenPolicy.CONVERSATION_SENDERS_NONE;
import static android.service.notification.ZenPolicy.PEOPLE_TYPE_ANYONE;
@@ -219,8 +225,8 @@
priorityCategories |= Policy.PRIORITY_CATEGORY_REMINDERS;
priorityCategories |= Policy.PRIORITY_CATEGORY_EVENTS;
priorityCategories |= Policy.PRIORITY_CATEGORY_CONVERSATIONS;
- suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_LIGHTS;
- suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_AMBIENT;
+ suppressedVisualEffects |= SUPPRESSED_EFFECT_LIGHTS;
+ suppressedVisualEffects |= SUPPRESSED_EFFECT_AMBIENT;
Policy expectedPolicy = new Policy(priorityCategories, priorityCallSenders,
priorityMessageSenders, suppressedVisualEffects, 0, priorityConversationsSenders);
@@ -256,8 +262,8 @@
priorityCategories |= Policy.PRIORITY_CATEGORY_REMINDERS;
priorityCategories |= Policy.PRIORITY_CATEGORY_EVENTS;
priorityCategories |= Policy.PRIORITY_CATEGORY_CONVERSATIONS;
- suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_LIGHTS;
- suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_AMBIENT;
+ suppressedVisualEffects |= SUPPRESSED_EFFECT_LIGHTS;
+ suppressedVisualEffects |= SUPPRESSED_EFFECT_AMBIENT;
Policy expectedPolicy = new Policy(priorityCategories, priorityCallSenders,
priorityMessageSenders, suppressedVisualEffects,
@@ -309,8 +315,8 @@
config.setAllowMessagesFrom(Policy.PRIORITY_SENDERS_STARRED);
config.setAllowConversationsFrom(CONVERSATION_SENDERS_NONE);
config.setSuppressedVisualEffects(config.getSuppressedVisualEffects()
- | Policy.SUPPRESSED_EFFECT_BADGE | Policy.SUPPRESSED_EFFECT_LIGHTS
- | Policy.SUPPRESSED_EFFECT_AMBIENT);
+ | Policy.SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_LIGHTS
+ | SUPPRESSED_EFFECT_AMBIENT);
}
ZenPolicy actual = config.getZenPolicy();
@@ -357,8 +363,8 @@
config.setAllowConversationsFrom(CONVERSATION_SENDERS_NONE);
config.setAllowPriorityChannels(false);
config.setSuppressedVisualEffects(config.getSuppressedVisualEffects()
- | Policy.SUPPRESSED_EFFECT_BADGE | Policy.SUPPRESSED_EFFECT_LIGHTS
- | Policy.SUPPRESSED_EFFECT_AMBIENT);
+ | Policy.SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_LIGHTS
+ | SUPPRESSED_EFFECT_AMBIENT);
}
ZenPolicy actual = config.getZenPolicy();
@@ -1063,6 +1069,43 @@
.isEqualTo("name");
}
+ @Test
+ public void toNotificationPolicy_withNewSuppressedEffects_returnsSuppressedEffects() {
+ ZenModeConfig config = getCustomConfig();
+ // From LegacyNotificationManagerTest.testSetNotificationPolicy_preP_setNewFields
+ // When a pre-P app sets SUPPRESSED_EFFECT_NOTIFICATION_LIST, it's converted by NMS into:
+ Policy policy = new Policy(0, 0, 0,
+ SUPPRESSED_EFFECT_FULL_SCREEN_INTENT | SUPPRESSED_EFFECT_LIGHTS
+ | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT);
+
+ config.applyNotificationPolicy(policy);
+ Policy result = config.toNotificationPolicy();
+
+ assertThat(suppressedEffectsOf(result)).isEqualTo(suppressedEffectsOf(policy));
+ }
+
+ @Test
+ public void toNotificationPolicy_withOldAndNewSuppressedEffects_returnsSuppressedEffects() {
+ ZenModeConfig config = getCustomConfig();
+ // From LegacyNotificationManagerTest.testSetNotificationPolicy_preP_setOldNewFields.
+ // When a pre-P app sets SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR, it's
+ // converted by NMS into:
+ Policy policy = new Policy(0, 0, 0,
+ SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
+ | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_PEEK
+ | SUPPRESSED_EFFECT_AMBIENT);
+
+ config.applyNotificationPolicy(policy);
+ Policy result = config.toNotificationPolicy();
+
+ assertThat(suppressedEffectsOf(result)).isEqualTo(suppressedEffectsOf(policy));
+ }
+
+ private static String suppressedEffectsOf(Policy policy) {
+ return suppressedEffectsToString(policy.suppressedVisualEffects) + "("
+ + policy.suppressedVisualEffects + ")";
+ }
+
private ZenModeConfig getMutedRingerConfig() {
ZenModeConfig config = new ZenModeConfig();
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeDiffTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeDiffTest.java
index 57587f7..9af0021 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeDiffTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeDiffTest.java
@@ -61,6 +61,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@@ -80,19 +81,6 @@
? Set.of("version", "manualRule", "automaticRules", "deletedRules")
: Set.of("version", "manualRule", "automaticRules");
- // Differences for flagged fields are only generated if the flag is enabled.
- // "Metadata" fields (userModifiedFields, deletionInstant, disabledOrigin) are not compared.
- private static final Set<String> ZEN_RULE_EXEMPT_FIELDS =
- android.app.Flags.modesApi()
- ? Set.of("userModifiedFields", "zenPolicyUserModifiedFields",
- "zenDeviceEffectsUserModifiedFields", "deletionInstant",
- "disabledOrigin")
- : Set.of(RuleDiff.FIELD_TYPE, RuleDiff.FIELD_TRIGGER_DESCRIPTION,
- RuleDiff.FIELD_ICON_RES, RuleDiff.FIELD_ALLOW_MANUAL,
- RuleDiff.FIELD_ZEN_DEVICE_EFFECTS, "userModifiedFields",
- "zenPolicyUserModifiedFields", "zenDeviceEffectsUserModifiedFields",
- "deletionInstant", "disabledOrigin");
-
// allowPriorityChannels is flagged by android.app.modes_api
public static final Set<String> ZEN_MODE_CONFIG_FLAGGED_FIELDS =
Set.of("allowPriorityChannels");
@@ -102,8 +90,7 @@
@Parameters(name = "{0}")
public static List<FlagsParameterization> getParams() {
- return FlagsParameterization.allCombinationsOf(
- FLAG_MODES_UI);
+ return FlagsParameterization.progressionOf(FLAG_MODES_API, FLAG_MODES_UI);
}
public ZenModeDiffTest(FlagsParameterization flags) {
@@ -140,7 +127,7 @@
ArrayMap<String, Object> expectedFrom = new ArrayMap<>();
ArrayMap<String, Object> expectedTo = new ArrayMap<>();
List<Field> fieldsForDiff = getFieldsForDiffCheck(
- ZenModeConfig.ZenRule.class, ZEN_RULE_EXEMPT_FIELDS);
+ ZenModeConfig.ZenRule.class, getZenRuleExemptFields());
generateFieldDiffs(r1, r2, fieldsForDiff, expectedFrom, expectedTo);
ZenModeDiff.RuleDiff d = new ZenModeDiff.RuleDiff(r1, r2);
@@ -158,6 +145,25 @@
}
}
+ private static Set<String> getZenRuleExemptFields() {
+ // "Metadata" fields are never compared.
+ Set<String> exemptFields = new LinkedHashSet<>(
+ Set.of("userModifiedFields", "zenPolicyUserModifiedFields",
+ "zenDeviceEffectsUserModifiedFields", "deletionInstant", "disabledOrigin"));
+ // Flagged fields are only compared if their flag is on.
+ if (!Flags.modesApi()) {
+ exemptFields.addAll(
+ Set.of(RuleDiff.FIELD_TYPE, RuleDiff.FIELD_TRIGGER_DESCRIPTION,
+ RuleDiff.FIELD_ICON_RES, RuleDiff.FIELD_ALLOW_MANUAL,
+ RuleDiff.FIELD_ZEN_DEVICE_EFFECTS,
+ RuleDiff.FIELD_LEGACY_SUPPRESSED_EFFECTS));
+ }
+ if (!(Flags.modesApi() && Flags.modesUi())) {
+ exemptFields.add(RuleDiff.FIELD_LEGACY_SUPPRESSED_EFFECTS);
+ }
+ return exemptFields;
+ }
+
@Test
public void testConfigDiff_addRemoveSame() {
// Default config, will test add, remove, and no change
diff --git a/services/tests/wmtests/res/xml/bookmarks.xml b/services/tests/wmtests/res/xml/bookmarks.xml
index 1549b2d..197b366 100644
--- a/services/tests/wmtests/res/xml/bookmarks.xml
+++ b/services/tests/wmtests/res/xml/bookmarks.xml
@@ -41,30 +41,33 @@
category="android.intent.category.APP_CALCULATOR"
shortcut="u" />
+ <bookmark
+ role="android.app.role.BROWSER"
+ shortcut="b"
+ shift="true" />
+
+ <bookmark
+ category="android.intent.category.APP_CONTACTS"
+ shortcut="c"
+ shift="true" />
+
+ <bookmark
+ package="com.test"
+ class="com.test.BookmarkTest"
+ shortcut="j"
+ shift="true" />
+
<!-- The following shortcuts will not be invoked by tests but are here to
provide test coverage of parsing the different types of shortcut. -->
<bookmark
package="com.test"
class="com.test.BookmarkTest"
- shortcut="a" />
+ shortcut="j" />
<bookmark
package="com.test2"
class="com.test.BookmarkTest"
shortcut="d" />
- <bookmark
- role="android.app.role.BROWSER"
- shortcut="b"
- shift="true" />
- <bookmark
- category="android.intent.category.APP_CONTACTS"
- shortcut="c"
- shift="true" />
- <bookmark
- package="com.test"
- class="com.test.BookmarkTest"
- shortcut="a"
- shift="true" />
<!-- It's intended that this package/class will NOT resolve so we test the resolution
failure case. -->
diff --git a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutManagerTests.java b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutManagerTests.java
index 50041d0..d147325 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutManagerTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutManagerTests.java
@@ -35,6 +35,7 @@
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.os.Handler;
@@ -89,9 +90,12 @@
testActivityInfo.applicationInfo = new ApplicationInfo();
testActivityInfo.packageName =
testActivityInfo.applicationInfo.packageName = "com.test";
+ ResolveInfo testResolveInfo = new ResolveInfo();
+ testResolveInfo.activityInfo = testActivityInfo;
doReturn(testActivityInfo).when(mPackageManager).getActivityInfo(
eq(new ComponentName("com.test", "com.test.BookmarkTest")), anyInt());
+ doReturn(testResolveInfo).when(mPackageManager).resolveActivity(anyObject(), anyInt());
doThrow(new PackageManager.NameNotFoundException("com.test3")).when(mPackageManager)
.getActivityInfo(eq(new ComponentName("com.test3", "com.test.BookmarkTest")),
anyInt());
diff --git a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
index 526c351..71f90a2 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
@@ -25,6 +25,7 @@
import static android.view.KeyEvent.KEYCODE_E;
import static android.view.KeyEvent.KEYCODE_ENTER;
import static android.view.KeyEvent.KEYCODE_H;
+import static android.view.KeyEvent.KEYCODE_J;
import static android.view.KeyEvent.KEYCODE_K;
import static android.view.KeyEvent.KEYCODE_M;
import static android.view.KeyEvent.KEYCODE_META_LEFT;
@@ -40,6 +41,7 @@
import static android.view.KeyEvent.KEYCODE_Z;
import android.app.role.RoleManager;
+import android.content.ComponentName;
import android.content.Intent;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
@@ -105,6 +107,17 @@
sendKeyCombination(new int[]{KEYCODE_META_LEFT, keyCode}, 0);
mPhoneWindowManager.assertLaunchRole(role);
}
+
+ sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_SHIFT_LEFT, KEYCODE_B}, 0);
+ mPhoneWindowManager.assertLaunchRole(RoleManager.ROLE_BROWSER);
+
+ sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_SHIFT_LEFT, KEYCODE_C}, 0);
+ mPhoneWindowManager.assertLaunchCategory(Intent.CATEGORY_APP_CONTACTS);
+
+ sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_SHIFT_LEFT, KEYCODE_J}, 0);
+ mPhoneWindowManager.assertActivityTargetLaunched(
+ new ComponentName("com.test", "com.test.BookmarkTest"));
+
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java b/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
index f5c8fb8..37e4fd6 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
@@ -43,11 +43,17 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.server.policy.WindowManagerPolicy.ACTION_PASS_TO_USER;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.ArgumentMatchers.eq;
import static java.util.Collections.unmodifiableMap;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.platform.test.flag.junit.SetFlagsRule;
@@ -76,6 +82,7 @@
public RuleChain rules = RuleChain.outerRule(mSettingsProviderRule).around(mSetFlagsRule);
private Resources mResources;
+ private PackageManager mPackageManager;
TestPhoneWindowManager mPhoneWindowManager;
DispatchedKeyHandler mDispatchedKeyHandler = event -> false;
Context mContext;
@@ -100,12 +107,25 @@
public void setup() {
mContext = spy(getInstrumentation().getTargetContext());
mResources = spy(mContext.getResources());
+ mPackageManager = spy(mContext.getPackageManager());
+ doReturn(mContext).when(mContext).createContextAsUser(anyObject(), anyInt());
doReturn(mResources).when(mContext).getResources();
doReturn(mSettingsProviderRule.mockContentResolver(mContext))
.when(mContext).getContentResolver();
XmlResourceParser testBookmarks = mResources.getXml(
com.android.frameworks.wmtests.R.xml.bookmarks);
doReturn(testBookmarks).when(mResources).getXml(com.android.internal.R.xml.bookmarks);
+
+ try {
+ // Keep packageName / className in sync with
+ // services/tests/wmtests/res/xml/bookmarks.xml
+ ActivityInfo testActivityInfo = new ActivityInfo();
+ testActivityInfo.applicationInfo = new ApplicationInfo();
+ testActivityInfo.packageName =
+ testActivityInfo.applicationInfo.packageName = "com.test";
+ doReturn(testActivityInfo).when(mPackageManager).getActivityInfo(
+ eq(new ComponentName("com.test", "com.test.BookmarkTest")), anyInt());
+ } catch (PackageManager.NameNotFoundException ignored) { }
}
diff --git a/services/tests/wmtests/src/com/android/server/policy/StemKeyGestureTests.java b/services/tests/wmtests/src/com/android/server/policy/StemKeyGestureTests.java
index 2e85025..9b92ff4 100644
--- a/services/tests/wmtests/src/com/android/server/policy/StemKeyGestureTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/StemKeyGestureTests.java
@@ -36,6 +36,7 @@
import android.provider.Settings;
import android.view.Display;
+import org.junit.Before;
import org.junit.Test;
/**
@@ -48,6 +49,13 @@
private static final String TEST_TARGET_ACTIVITY = "com.android.server.policy/.TestActivity";
+ @Before
+ public void setup() {
+ super.setup();
+ overrideResource(com.android.internal.R.integer.config_longPressOnStemPrimaryBehavior,
+ LONG_PRESS_PRIMARY_LAUNCH_VOICE_ASSISTANT);
+ }
+
/**
* Stem single key should not launch behavior during set up.
*/
@@ -186,6 +194,26 @@
}
@Test
+ public void stemLongKey_appHasOverridePermission_consumedByApp_triggerStatusBarToStartAssist() {
+ overrideBehavior(
+ STEM_PRIMARY_BUTTON_LONG_PRESS,
+ LONG_PRESS_PRIMARY_LAUNCH_VOICE_ASSISTANT);
+ setUpPhoneWindowManager(/* supportSettingsUpdate= */ true);
+ mPhoneWindowManager.overrideShouldEarlyShortPressOnStemPrimary(false);
+ mPhoneWindowManager.setupAssistForLaunch();
+ mPhoneWindowManager.overrideSearchManager(null);
+ mPhoneWindowManager.overrideStatusBarManagerInternal();
+ mPhoneWindowManager.overrideIsUserSetupComplete(true);
+ mPhoneWindowManager.overrideFocusedWindowButtonOverridePermission(true);
+
+ setDispatchedKeyHandler(keyEvent -> true);
+
+ sendKey(KEYCODE_STEM_PRIMARY, /* longPress= */ true);
+
+ mPhoneWindowManager.assertStatusBarStartAssist();
+ }
+
+ @Test
public void stemDoubleKey_EarlyShortPress_AllAppsThenSwitchToMostRecent()
throws RemoteException {
overrideBehavior(STEM_PRIMARY_BUTTON_SHORT_PRESS, SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS);
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
index 2b7e7ab..6f8c91c 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -50,7 +50,6 @@
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.CALLS_REAL_METHODS;
import static org.mockito.Mockito.after;
-import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mockingDetails;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.withSettings;
@@ -311,13 +310,6 @@
eq(AccessibilityManager.class));
doReturn(false).when(mAccessibilityManager).isEnabled();
doReturn(false).when(mPackageManager).hasSystemFeature(any());
- try {
- doThrow(new PackageManager.NameNotFoundException("test")).when(mPackageManager)
- .getActivityInfo(any(), anyInt());
- doReturn(new String[] { "testPackage" }).when(mPackageManager)
- .canonicalToCurrentPackageNames(any());
- } catch (PackageManager.NameNotFoundException ignored) { }
-
doReturn(false).when(mTelecomManager).isInCall();
doReturn(false).when(mTelecomManager).isRinging();
doReturn(mTelecomManager).when(mPhoneWindowManager).getTelecommService();
@@ -740,7 +732,6 @@
Mockito.clearInvocations(mContext);
}
-
void assertShowRecentApps() {
mTestLooper.dispatchAll();
verify(mStatusBarManagerInternal).showRecentApps(anyBoolean());
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 faaa80f..ea825c7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -18,10 +18,6 @@
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
-import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -119,7 +115,6 @@
import android.app.ActivityOptions;
import android.app.AppOpsManager;
-import android.app.ICompatCameraControlCallback;
import android.app.PictureInPictureParams;
import android.app.servertransaction.ActivityConfigurationChangeItem;
import android.app.servertransaction.ClientTransaction;
@@ -3483,178 +3478,6 @@
assertFalse(app.mActivityRecord.isSurfaceShowing());
}
- @Test
- public void testUpdateCameraCompatState_flagIsEnabled_controlStateIsUpdated() {
- final ActivityRecord activity = createActivityWithTask();
- // Mock a flag being enabled.
- doReturn(true).when(activity).isCameraCompatControlEnabled();
-
- activity.updateCameraCompatState(/* showControl */ true,
- /* transformationApplied */ false, /* callback */ null);
-
- assertEquals(activity.getCameraCompatControlState(),
- CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED);
-
- activity.updateCameraCompatState(/* showControl */ true,
- /* transformationApplied */ true, /* callback */ null);
-
- assertEquals(activity.getCameraCompatControlState(),
- CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED);
-
- activity.updateCameraCompatState(/* showControl */ false,
- /* transformationApplied */ false, /* callback */ null);
-
- assertEquals(activity.getCameraCompatControlState(), CAMERA_COMPAT_CONTROL_HIDDEN);
-
- activity.updateCameraCompatState(/* showControl */ false,
- /* transformationApplied */ true, /* callback */ null);
-
- assertEquals(activity.getCameraCompatControlState(), CAMERA_COMPAT_CONTROL_HIDDEN);
- }
-
- @Test
- public void testUpdateCameraCompatState_flagIsDisabled_controlStateIsHidden() {
- final ActivityRecord activity = createActivityWithTask();
- // Mock a flag being disabled.
- doReturn(false).when(activity).isCameraCompatControlEnabled();
-
- activity.updateCameraCompatState(/* showControl */ true,
- /* transformationApplied */ false, /* callback */ null);
-
- assertEquals(activity.getCameraCompatControlState(), CAMERA_COMPAT_CONTROL_HIDDEN);
-
- activity.updateCameraCompatState(/* showControl */ true,
- /* transformationApplied */ true, /* callback */ null);
-
- assertEquals(activity.getCameraCompatControlState(), CAMERA_COMPAT_CONTROL_HIDDEN);
- }
-
- @Test
- public void testUpdateCameraCompatStateFromUser_clickedOnDismiss() throws RemoteException {
- final ActivityRecord activity = createActivityWithTask();
- // Mock a flag being enabled.
- doReturn(true).when(activity).isCameraCompatControlEnabled();
-
- ICompatCameraControlCallback callback = getCompatCameraControlCallback();
- spyOn(callback);
- activity.updateCameraCompatState(/* showControl */ true,
- /* transformationApplied */ false, callback);
-
- assertEquals(activity.getCameraCompatControlState(),
- CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED);
-
- // Clicking on the button.
- activity.updateCameraCompatStateFromUser(CAMERA_COMPAT_CONTROL_DISMISSED);
-
- verify(callback, never()).revertCameraCompatTreatment();
- verify(callback, never()).applyCameraCompatTreatment();
- assertEquals(activity.getCameraCompatControlState(), CAMERA_COMPAT_CONTROL_DISMISSED);
-
- // All following updates are ignored.
- activity.updateCameraCompatState(/* showControl */ true,
- /* transformationApplied */ false, /* callback */ null);
-
- assertEquals(activity.getCameraCompatControlState(), CAMERA_COMPAT_CONTROL_DISMISSED);
-
- activity.updateCameraCompatState(/* showControl */ true,
- /* transformationApplied */ true, /* callback */ null);
-
- assertEquals(activity.getCameraCompatControlState(), CAMERA_COMPAT_CONTROL_DISMISSED);
-
- activity.updateCameraCompatState(/* showControl */ false,
- /* transformationApplied */ true, /* callback */ null);
-
- assertEquals(activity.getCameraCompatControlState(), CAMERA_COMPAT_CONTROL_DISMISSED);
- }
-
- @Test
- public void testUpdateCameraCompatStateFromUser_clickedOnApplyTreatment()
- throws RemoteException {
- final ActivityRecord activity = createActivityWithTask();
- // Mock a flag being enabled.
- doReturn(true).when(activity).isCameraCompatControlEnabled();
-
- ICompatCameraControlCallback callback = getCompatCameraControlCallback();
- spyOn(callback);
- activity.updateCameraCompatState(/* showControl */ true,
- /* transformationApplied */ false, callback);
-
- assertEquals(activity.getCameraCompatControlState(),
- CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED);
-
- // Clicking on the button.
- activity.updateCameraCompatStateFromUser(CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED);
-
- verify(callback, never()).revertCameraCompatTreatment();
- verify(callback).applyCameraCompatTreatment();
- assertEquals(activity.getCameraCompatControlState(),
- CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED);
-
- // Request from the client to show the control are ignored respecting the user choice.
- activity.updateCameraCompatState(/* showControl */ true,
- /* transformationApplied */ false, /* callback */ null);
-
- assertEquals(activity.getCameraCompatControlState(),
- CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED);
-
- // Request from the client to hide the control is respected.
- activity.updateCameraCompatState(/* showControl */ false,
- /* transformationApplied */ true, /* callback */ null);
-
- assertEquals(activity.getCameraCompatControlState(), CAMERA_COMPAT_CONTROL_HIDDEN);
-
- // Request from the client to show the control again is respected.
- activity.updateCameraCompatState(/* showControl */ true,
- /* transformationApplied */ false, /* callback */ null);
-
- assertEquals(activity.getCameraCompatControlState(),
- CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED);
- }
-
- @Test
- public void testUpdateCameraCompatStateFromUser_clickedOnRevertTreatment()
- throws RemoteException {
- final ActivityRecord activity = createActivityWithTask();
- // Mock a flag being enabled.
- doReturn(true).when(activity).isCameraCompatControlEnabled();
-
- ICompatCameraControlCallback callback = getCompatCameraControlCallback();
- spyOn(callback);
- activity.updateCameraCompatState(/* showControl */ true,
- /* transformationApplied */ true, callback);
-
- assertEquals(activity.getCameraCompatControlState(),
- CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED);
-
- // Clicking on the button.
- activity.updateCameraCompatStateFromUser(CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED);
-
- verify(callback).revertCameraCompatTreatment();
- verify(callback, never()).applyCameraCompatTreatment();
- assertEquals(activity.getCameraCompatControlState(),
- CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED);
-
- // Request from the client to show the control are ignored respecting the user choice.
- activity.updateCameraCompatState(/* showControl */ true,
- /* transformationApplied */ true, /* callback */ null);
-
- assertEquals(activity.getCameraCompatControlState(),
- CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED);
-
- // Request from the client to hide the control is respected.
- activity.updateCameraCompatState(/* showControl */ false,
- /* transformationApplied */ true, /* callback */ null);
-
- assertEquals(activity.getCameraCompatControlState(), CAMERA_COMPAT_CONTROL_HIDDEN);
-
- // Request from the client to show the control again is respected.
- activity.updateCameraCompatState(/* showControl */ true,
- /* transformationApplied */ true, /* callback */ null);
-
- assertEquals(activity.getCameraCompatControlState(),
- CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED);
- }
-
@Test // b/162542125
public void testInputDispatchTimeout() throws RemoteException {
final ActivityRecord activity = createActivityWithTask();
@@ -3818,16 +3641,6 @@
assertTrue(appWindow.mResizeReported);
}
- private ICompatCameraControlCallback getCompatCameraControlCallback() {
- return new ICompatCameraControlCallback.Stub() {
- @Override
- public void applyCameraCompatTreatment() {}
-
- @Override
- public void revertCameraCompatTreatment() {}
- };
- }
-
private void assertHasStartingWindow(ActivityRecord atoken) {
assertNotNull(atoken.mStartingSurface);
assertNotNull(atoken.mStartingData);
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java
index 220248c..f8cf97e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java
@@ -178,6 +178,10 @@
doReturn(enabled).when(mActivityStack.top()).shouldCreateCompatDisplayInsets();
}
+ void setTopActivityInSizeCompatMode(boolean inScm) {
+ doReturn(inScm).when(mActivityStack.top()).inSizeCompatMode();
+ }
+
void setShouldApplyUserFullscreenOverride(boolean enabled) {
doReturn(enabled).when(mActivityStack.top().mAppCompatController
.getAppCompatAspectRatioOverrides()).shouldApplyUserFullscreenOverride();
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatUtilsTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatUtilsTest.java
new file mode 100644
index 0000000..9e242ee
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatUtilsTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static org.mockito.Mockito.when;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.annotation.NonNull;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+
+import java.util.function.Consumer;
+
+/**
+ * Test class for {@link AppCompatUtils}.
+ * <p>
+ * Build/Install/Run:
+ * atest WmTests:AppCompatUtilsTest
+ */
+@Presubmit
+@RunWith(WindowTestRunner.class)
+public class AppCompatUtilsTest extends WindowTestsBase {
+
+ @Test
+ public void getLetterboxReasonString_inSizeCompatMode() {
+ runTestScenario((robot) -> {
+ robot.activity().setTopActivityInSizeCompatMode(/* inScm */ true);
+
+ robot.checkTopActivityLetterboxReason(/* expected */ "SIZE_COMPAT_MODE");
+ });
+ }
+
+ @Test
+ public void getLetterboxReasonString_fixedOrientation() {
+ runTestScenario((robot) -> {
+ robot.activity().checkTopActivityInSizeCompatMode(/* inScm */ false);
+ robot.setIsLetterboxedForFixedOrientationAndAspectRatio(
+ /* forFixedOrientationAndAspectRatio */ true);
+
+ robot.checkTopActivityLetterboxReason(/* expected */ "FIXED_ORIENTATION");
+ });
+ }
+
+ @Test
+ public void getLetterboxReasonString_isLetterboxedForDisplayCutout() {
+ runTestScenario((robot) -> {
+ robot.activity().checkTopActivityInSizeCompatMode(/* inScm */ false);
+ robot.setIsLetterboxedForFixedOrientationAndAspectRatio(
+ /* forFixedOrientationAndAspectRatio */ false);
+ robot.setIsLetterboxedForDisplayCutout(/* displayCutout */ true);
+
+ robot.checkTopActivityLetterboxReason(/* expected */ "DISPLAY_CUTOUT");
+ });
+ }
+
+ @Test
+ public void getLetterboxReasonString_aspectRatio() {
+ runTestScenario((robot) -> {
+ robot.activity().checkTopActivityInSizeCompatMode(/* inScm */ false);
+ robot.setIsLetterboxedForFixedOrientationAndAspectRatio(
+ /* forFixedOrientationAndAspectRatio */ false);
+ robot.setIsLetterboxedForDisplayCutout(/* displayCutout */ false);
+ robot.setIsLetterboxedForAspectRatioOnly(/* forAspectRatio */ true);
+
+ robot.checkTopActivityLetterboxReason(/* expected */ "ASPECT_RATIO");
+ });
+ }
+
+ @Test
+ public void getLetterboxReasonString_unknownReason() {
+ runTestScenario((robot) -> {
+ robot.activity().checkTopActivityInSizeCompatMode(/* inScm */ false);
+ robot.setIsLetterboxedForFixedOrientationAndAspectRatio(
+ /* forFixedOrientationAndAspectRatio */ false);
+ robot.setIsLetterboxedForDisplayCutout(/* displayCutout */ false);
+ robot.setIsLetterboxedForAspectRatioOnly(/* forAspectRatio */ false);
+
+ robot.checkTopActivityLetterboxReason(/* expected */ "UNKNOWN_REASON");
+ });
+ }
+
+
+ /**
+ * Runs a test scenario providing a Robot.
+ */
+ void runTestScenario(@NonNull Consumer<AppCompatUtilsRobotTest> consumer) {
+ final AppCompatUtilsRobotTest robot = new AppCompatUtilsRobotTest(mWm, mAtm, mSupervisor);
+ consumer.accept(robot);
+ }
+
+ private static class AppCompatUtilsRobotTest extends AppCompatRobotBase {
+
+ private final WindowState mWindowState;
+
+ AppCompatUtilsRobotTest(@NonNull WindowManagerService wm,
+ @NonNull ActivityTaskManagerService atm,
+ @NonNull ActivityTaskSupervisor supervisor) {
+ super(wm, atm, supervisor);
+ activity().createActivityWithComponent();
+ mWindowState = Mockito.mock(WindowState.class);
+ }
+
+ void setIsLetterboxedForFixedOrientationAndAspectRatio(
+ boolean forFixedOrientationAndAspectRatio) {
+ when(activity().top().mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio())
+ .thenReturn(forFixedOrientationAndAspectRatio);
+ }
+
+ void setIsLetterboxedForAspectRatioOnly(boolean forAspectRatio) {
+ when(activity().top().mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForAspectRatioOnly()).thenReturn(forAspectRatio);
+ }
+
+ void setIsLetterboxedForDisplayCutout(boolean displayCutout) {
+ when(mWindowState.isLetterboxedForDisplayCutout()).thenReturn(displayCutout);
+ }
+
+ void checkTopActivityLetterboxReason(@NonNull String expected) {
+ Assert.assertEquals(expected,
+ AppCompatUtils.getLetterboxReasonString(activity().top(), mWindowState));
+ }
+
+ }
+
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
index a159ce3..44837d7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -58,6 +58,7 @@
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsDisabled;
import android.util.ArraySet;
import android.view.WindowManager;
import android.window.BackAnimationAdapter;
@@ -72,6 +73,7 @@
import android.window.WindowOnBackInvokedDispatcher;
import com.android.server.LocalServices;
+import com.android.window.flags.Flags;
import org.junit.Before;
import org.junit.Test;
@@ -612,6 +614,7 @@
}
@Test
+ @RequiresFlagsDisabled(Flags.FLAG_MIGRATE_PREDICTIVE_BACK_TRANSITION)
public void testTransitionHappensCancelNavigation() {
// Create a floating task and a fullscreen task, then navigating on fullscreen task.
// The navigation should not been cancelled when transition happens on floating task, and
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
index bb5887d..58f8eb2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
@@ -33,6 +33,7 @@
import android.app.WindowConfiguration;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.IntentSender;
import android.content.pm.ActivityInfo;
import android.os.Process;
import android.util.ArraySet;
@@ -40,12 +41,14 @@
import android.window.DisplayWindowPolicyController;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.Set;
+import java.util.function.Supplier;
/**
* Tests for the {@link DisplayWindowPolicyController} class.
@@ -224,7 +227,7 @@
assertEquals(result, START_ABORTED);
}
- private class TestDisplayWindowPolicyController extends DisplayWindowPolicyController {
+ private static class TestDisplayWindowPolicyController extends DisplayWindowPolicyController {
public ComponentName DISALLOWED_ACTIVITY =
new ComponentName("fake.package", "DisallowedActivity");
@@ -236,7 +239,8 @@
@Override
public boolean canActivityBeLaunched(@NonNull ActivityInfo activity, Intent intent,
@WindowConfiguration.WindowingMode int windowingMode, int launchingFromDisplayId,
- boolean isNewTask) {
+ boolean isNewTask, boolean isResultExpected,
+ @Nullable Supplier<IntentSender> intentSender) {
return canContainActivity(activity, windowingMode, launchingFromDisplayId, isNewTask);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java
index 2e0d4d4..2f2b473 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java
@@ -31,7 +31,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.testng.Assert.assertFalse;
@@ -357,8 +356,6 @@
@Test
public void testRemovesStaleDisplaySettings_defaultDisplay_removesStaleDisplaySettings() {
- assumeTrue(com.android.window.flags.Flags.perUserDisplayWindowSettings());
-
// Write density setting for second display then remove it.
final DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider(
mDefaultVendorSettingsStorage, mOverrideSettingsStorage);
@@ -387,8 +384,6 @@
@Test
public void testRemovesStaleDisplaySettings_displayNotInLayout_keepsDisplaySettings() {
- assumeTrue(com.android.window.flags.Flags.perUserDisplayWindowSettings());
-
// Write density setting for primary display.
final DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider(
mDefaultVendorSettingsStorage, mOverrideSettingsStorage);
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
index fbc4c7b..ffaa2d8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
@@ -66,7 +66,7 @@
mLetterbox = new Letterbox(mSurfaces, StubTransaction::new,
() -> mAreCornersRounded, () -> Color.valueOf(mColor),
() -> mHasWallpaperBackground, () -> mBlurRadius, () -> mDarkScrimAlpha,
- /* doubleTapCallbackX= */ x -> {}, /* doubleTapCallbackY= */ y -> {},
+ mock(AppCompatReachabilityPolicy.class),
() -> mParentSurface);
mTransaction = spy(StubTransaction.class);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
index 61a6f31..33df5d8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
@@ -300,7 +300,9 @@
// Vertical thin letterbox disabled
doReturn(-1).when(mActivity.mWmService.mAppCompatConfiguration)
.getThinLetterboxHeightPx();
- assertFalse(mController.isVerticalThinLetterboxed());
+ final AppCompatReachabilityOverrides reachabilityOverrides = mActivity.mAppCompatController
+ .getAppCompatReachabilityOverrides();
+ assertFalse(reachabilityOverrides.isVerticalThinLetterboxed());
// Define a Task 100x100
final Task task = mock(Task.class);
doReturn(new Rect(0, 0, 100, 100)).when(task).getBounds();
@@ -309,21 +311,21 @@
// Vertical thin letterbox disabled without Task
doReturn(null).when(mActivity).getTask();
- assertFalse(mController.isVerticalThinLetterboxed());
+ assertFalse(reachabilityOverrides.isVerticalThinLetterboxed());
// Assign a Task for the Activity
doReturn(task).when(mActivity).getTask();
// (task.width() - act.width()) / 2 = 5 < 10
doReturn(new Rect(5, 5, 95, 95)).when(mActivity).getBounds();
- assertTrue(mController.isVerticalThinLetterboxed());
+ assertTrue(reachabilityOverrides.isVerticalThinLetterboxed());
// (task.width() - act.width()) / 2 = 10 = 10
doReturn(new Rect(10, 10, 90, 90)).when(mActivity).getBounds();
- assertTrue(mController.isVerticalThinLetterboxed());
+ assertTrue(reachabilityOverrides.isVerticalThinLetterboxed());
// (task.width() - act.width()) / 2 = 11 > 10
doReturn(new Rect(11, 11, 89, 89)).when(mActivity).getBounds();
- assertFalse(mController.isVerticalThinLetterboxed());
+ assertFalse(reachabilityOverrides.isVerticalThinLetterboxed());
}
@Test
@@ -331,7 +333,9 @@
// Horizontal thin letterbox disabled
doReturn(-1).when(mActivity.mWmService.mAppCompatConfiguration)
.getThinLetterboxWidthPx();
- assertFalse(mController.isHorizontalThinLetterboxed());
+ final AppCompatReachabilityOverrides reachabilityOverrides = mActivity.mAppCompatController
+ .getAppCompatReachabilityOverrides();
+ assertFalse(reachabilityOverrides.isHorizontalThinLetterboxed());
// Define a Task 100x100
final Task task = mock(Task.class);
doReturn(new Rect(0, 0, 100, 100)).when(task).getBounds();
@@ -340,51 +344,55 @@
// Vertical thin letterbox disabled without Task
doReturn(null).when(mActivity).getTask();
- assertFalse(mController.isHorizontalThinLetterboxed());
+ assertFalse(reachabilityOverrides.isHorizontalThinLetterboxed());
// Assign a Task for the Activity
doReturn(task).when(mActivity).getTask();
// (task.height() - act.height()) / 2 = 5 < 10
doReturn(new Rect(5, 5, 95, 95)).when(mActivity).getBounds();
- assertTrue(mController.isHorizontalThinLetterboxed());
+ assertTrue(reachabilityOverrides.isHorizontalThinLetterboxed());
// (task.height() - act.height()) / 2 = 10 = 10
doReturn(new Rect(10, 10, 90, 90)).when(mActivity).getBounds();
- assertTrue(mController.isHorizontalThinLetterboxed());
+ assertTrue(reachabilityOverrides.isHorizontalThinLetterboxed());
// (task.height() - act.height()) / 2 = 11 > 10
doReturn(new Rect(11, 11, 89, 89)).when(mActivity).getBounds();
- assertFalse(mController.isHorizontalThinLetterboxed());
+ assertFalse(reachabilityOverrides.isHorizontalThinLetterboxed());
}
@Test
@EnableFlags(Flags.FLAG_DISABLE_THIN_LETTERBOXING_POLICY)
public void testAllowReachabilityForThinLetterboxWithFlagEnabled() {
- spyOn(mController);
- doReturn(true).when(mController).isVerticalThinLetterboxed();
- assertFalse(mController.allowVerticalReachabilityForThinLetterbox());
- doReturn(true).when(mController).isHorizontalThinLetterboxed();
- assertFalse(mController.allowHorizontalReachabilityForThinLetterbox());
+ final AppCompatReachabilityOverrides reachabilityOverrides =
+ mActivity.mAppCompatController.getAppCompatReachabilityOverrides();
+ spyOn(reachabilityOverrides);
+ doReturn(true).when(reachabilityOverrides).isVerticalThinLetterboxed();
+ assertFalse(reachabilityOverrides.allowVerticalReachabilityForThinLetterbox());
+ doReturn(true).when(reachabilityOverrides).isHorizontalThinLetterboxed();
+ assertFalse(reachabilityOverrides.allowHorizontalReachabilityForThinLetterbox());
- doReturn(false).when(mController).isVerticalThinLetterboxed();
- assertTrue(mController.allowVerticalReachabilityForThinLetterbox());
- doReturn(false).when(mController).isHorizontalThinLetterboxed();
- assertTrue(mController.allowHorizontalReachabilityForThinLetterbox());
+ doReturn(false).when(reachabilityOverrides).isVerticalThinLetterboxed();
+ assertTrue(reachabilityOverrides.allowVerticalReachabilityForThinLetterbox());
+ doReturn(false).when(reachabilityOverrides).isHorizontalThinLetterboxed();
+ assertTrue(reachabilityOverrides.allowHorizontalReachabilityForThinLetterbox());
}
@Test
@DisableFlags(Flags.FLAG_DISABLE_THIN_LETTERBOXING_POLICY)
public void testAllowReachabilityForThinLetterboxWithFlagDisabled() {
- spyOn(mController);
- doReturn(true).when(mController).isVerticalThinLetterboxed();
- assertTrue(mController.allowVerticalReachabilityForThinLetterbox());
- doReturn(true).when(mController).isHorizontalThinLetterboxed();
- assertTrue(mController.allowHorizontalReachabilityForThinLetterbox());
+ final AppCompatReachabilityOverrides reachabilityOverrides =
+ mActivity.mAppCompatController.getAppCompatReachabilityOverrides();
+ spyOn(reachabilityOverrides);
+ doReturn(true).when(reachabilityOverrides).isVerticalThinLetterboxed();
+ assertTrue(reachabilityOverrides.allowVerticalReachabilityForThinLetterbox());
+ doReturn(true).when(reachabilityOverrides).isHorizontalThinLetterboxed();
+ assertTrue(reachabilityOverrides.allowHorizontalReachabilityForThinLetterbox());
- doReturn(false).when(mController).isVerticalThinLetterboxed();
- assertTrue(mController.allowVerticalReachabilityForThinLetterbox());
- doReturn(false).when(mController).isHorizontalThinLetterboxed();
- assertTrue(mController.allowHorizontalReachabilityForThinLetterbox());
+ doReturn(false).when(reachabilityOverrides).isVerticalThinLetterboxed();
+ assertTrue(reachabilityOverrides.allowVerticalReachabilityForThinLetterbox());
+ doReturn(false).when(reachabilityOverrides).isHorizontalThinLetterboxed();
+ assertTrue(reachabilityOverrides.allowHorizontalReachabilityForThinLetterbox());
}
@Test
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 ed93a8c..3e68b6b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -281,7 +281,8 @@
if (horizontalReachability) {
final Consumer<Integer> doubleClick =
(Integer x) -> {
- mActivity.mLetterboxUiController.handleHorizontalDoubleTap(x);
+ mActivity.mAppCompatController.getAppCompatReachabilityPolicy()
+ .handleDoubleTap(x, displayHeight / 2);
mActivity.mRootWindowContainer.performSurfacePlacement();
};
@@ -310,7 +311,8 @@
} else {
final Consumer<Integer> doubleClick =
(Integer y) -> {
- mActivity.mLetterboxUiController.handleVerticalDoubleTap(y);
+ mActivity.mAppCompatController.getAppCompatReachabilityPolicy()
+ .handleDoubleTap(displayWidth / 2, y);
mActivity.mRootWindowContainer.performSurfacePlacement();
};
@@ -373,7 +375,8 @@
final Consumer<Integer> doubleClick =
(Integer y) -> {
- activity.mLetterboxUiController.handleVerticalDoubleTap(y);
+ activity.mAppCompatController.getAppCompatReachabilityPolicy()
+ .handleDoubleTap(dw / 2, y);
activity.mRootWindowContainer.performSurfacePlacement();
};
@@ -3431,9 +3434,10 @@
mActivity.getWindowConfiguration().setBounds(null);
setUpAllowThinLetterboxed(/* thinLetterboxAllowed */ false);
-
- assertFalse(mActivity.mLetterboxUiController.isVerticalReachabilityEnabled());
- assertFalse(mActivity.mLetterboxUiController.isHorizontalReachabilityEnabled());
+ final AppCompatReachabilityOverrides reachabilityOverrides =
+ mActivity.mAppCompatController.getAppCompatReachabilityOverrides();
+ assertFalse(reachabilityOverrides.isVerticalReachabilityEnabled());
+ assertFalse(reachabilityOverrides.isHorizontalReachabilityEnabled());
}
@Test
@@ -3456,7 +3460,8 @@
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
// Horizontal reachability is disabled because the app is in split screen.
- assertFalse(mActivity.mLetterboxUiController.isHorizontalReachabilityEnabled());
+ assertFalse(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .isHorizontalReachabilityEnabled());
}
@Test
@@ -3479,7 +3484,8 @@
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
// Vertical reachability is disabled because the app is in split screen.
- assertFalse(mActivity.mLetterboxUiController.isVerticalReachabilityEnabled());
+ assertFalse(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .isVerticalReachabilityEnabled());
}
@Test
@@ -3501,7 +3507,8 @@
// Vertical reachability is disabled because the app does not match parent width
assertNotEquals(mActivity.getScreenResolvedBounds().width(),
mActivity.mDisplayContent.getBounds().width());
- assertFalse(mActivity.mLetterboxUiController.isVerticalReachabilityEnabled());
+ assertFalse(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .isVerticalReachabilityEnabled());
}
@Test
@@ -3518,7 +3525,8 @@
assertEquals(new Rect(0, 0, 0, 0), mActivity.getBounds());
// Vertical reachability is still enabled as resolved bounds is not empty
- assertTrue(mActivity.mLetterboxUiController.isVerticalReachabilityEnabled());
+ assertTrue(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .isVerticalReachabilityEnabled());
}
@Test
@@ -3535,7 +3543,8 @@
assertEquals(new Rect(0, 0, 0, 0), mActivity.getBounds());
// Horizontal reachability is still enabled as resolved bounds is not empty
- assertTrue(mActivity.mLetterboxUiController.isHorizontalReachabilityEnabled());
+ assertTrue(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .isHorizontalReachabilityEnabled());
}
@Test
@@ -3549,7 +3558,8 @@
prepareMinAspectRatio(mActivity, OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
SCREEN_ORIENTATION_PORTRAIT);
- assertTrue(mActivity.mLetterboxUiController.isHorizontalReachabilityEnabled());
+ assertTrue(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .isHorizontalReachabilityEnabled());
}
@Test
@@ -3563,7 +3573,8 @@
prepareMinAspectRatio(mActivity, OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
SCREEN_ORIENTATION_LANDSCAPE);
- assertTrue(mActivity.mLetterboxUiController.isVerticalReachabilityEnabled());
+ assertTrue(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .isVerticalReachabilityEnabled());
}
@Test
@@ -3585,7 +3596,8 @@
// Horizontal reachability is disabled because the app does not match parent height
assertNotEquals(mActivity.getScreenResolvedBounds().height(),
mActivity.mDisplayContent.getBounds().height());
- assertFalse(mActivity.mLetterboxUiController.isHorizontalReachabilityEnabled());
+ assertFalse(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .isHorizontalReachabilityEnabled());
}
@Test
@@ -3607,7 +3619,8 @@
// Horizontal reachability is enabled because the app matches parent height
assertEquals(mActivity.getScreenResolvedBounds().height(),
mActivity.mDisplayContent.getBounds().height());
- assertTrue(mActivity.mLetterboxUiController.isHorizontalReachabilityEnabled());
+ assertTrue(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .isHorizontalReachabilityEnabled());
}
@Test
@@ -3629,7 +3642,8 @@
// Vertical reachability is enabled because the app matches parent width
assertEquals(mActivity.getScreenResolvedBounds().width(),
mActivity.mDisplayContent.getBounds().width());
- assertTrue(mActivity.mLetterboxUiController.isVerticalReachabilityEnabled());
+ assertTrue(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .isVerticalReachabilityEnabled());
}
@Test
@@ -4306,15 +4320,17 @@
resizeDisplay(mTask.mDisplayContent, 1400, 2800);
// Make sure app doesn't jump to top (default tabletop position) when unfolding.
- assertEquals(1.0f, mActivity.mLetterboxUiController.getVerticalPositionMultiplier(
- mActivity.getParent().getConfiguration()), 0);
+ assertEquals(1.0f, mActivity.mAppCompatController
+ .getAppCompatReachabilityOverrides().getVerticalPositionMultiplier(mActivity
+ .getParent().getConfiguration()), 0);
// Simulate display fully open after unfolding.
setFoldablePosture(false /* isHalfFolded */, false /* isTabletop */);
doReturn(false).when(mActivity.mDisplayContent).inTransition();
- assertEquals(1.0f, mActivity.mLetterboxUiController.getVerticalPositionMultiplier(
- mActivity.getParent().getConfiguration()), 0);
+ assertEquals(1.0f, mActivity.mAppCompatController
+ .getAppCompatReachabilityOverrides().getVerticalPositionMultiplier(mActivity
+ .getParent().getConfiguration()), 0);
}
@Test
@@ -4809,10 +4825,12 @@
}
private void setUpAllowThinLetterboxed(boolean thinLetterboxAllowed) {
- spyOn(mActivity.mLetterboxUiController);
- doReturn(thinLetterboxAllowed).when(mActivity.mLetterboxUiController)
+ final AppCompatReachabilityOverrides reachabilityOverrides =
+ mActivity.mAppCompatController.getAppCompatReachabilityOverrides();
+ spyOn(reachabilityOverrides);
+ doReturn(thinLetterboxAllowed).when(reachabilityOverrides)
.allowVerticalReachabilityForThinLetterbox();
- doReturn(thinLetterboxAllowed).when(mActivity.mLetterboxUiController)
+ doReturn(thinLetterboxAllowed).when(reachabilityOverrides)
.allowHorizontalReachabilityForThinLetterbox();
}
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 720457e..49e349c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -2021,7 +2021,7 @@
@EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
- public void testOverrideAnimationOptionsToInfoIfNecessary_nonCustomAnimOptions() {
+ public void testOverrideAnimationOptionsToInfoIfNecessary_fromStyleAnimOptions() {
initializeOverrideAnimationOptionsTest();
TransitionInfo.AnimationOptions options = TransitionInfo.AnimationOptions
.makeCommonAnimOptions("testPackage");
@@ -2047,6 +2047,32 @@
@EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
+ public void testOverrideAnimationOptionsToInfoIfNecessary_sceneAnimOptions() {
+ initializeOverrideAnimationOptionsTest();
+ TransitionInfo.AnimationOptions options = TransitionInfo.AnimationOptions
+ .makeSceneTransitionAnimOptions();
+ mTransition.setOverrideAnimation(options, null /* startCallback */,
+ null /* finishCallback */);
+
+ mTransition.overrideAnimationOptionsToInfoIfNecessary(mInfo);
+
+ final TransitionInfo.Change displayChange = mInfo.getChanges().get(0);
+ final TransitionInfo.Change taskChange = mInfo.getChanges().get(1);
+ final TransitionInfo.Change embeddedTfChange = mInfo.getChanges().get(2);
+ final TransitionInfo.Change activityChange = mInfo.getChanges().get(3);
+
+ assertNull("Display change's AnimationOptions must not be overridden.",
+ displayChange.getAnimationOptions());
+ assertEquals("Task change's AnimationOptions must be overridden.",
+ options, taskChange.getAnimationOptions());
+ assertNull("Embedded TF change's AnimationOptions must not be overridden.",
+ embeddedTfChange.getAnimationOptions());
+ assertEquals("Activity change's AnimationOptions must be overridden.",
+ options, activityChange.getAnimationOptions());
+ }
+
+ @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
+ @Test
public void testOverrideAnimationOptionsToInfoIfNecessary_crossProfileAnimOptions() {
initializeOverrideAnimationOptionsTest();
TransitionInfo.AnimationOptions options = TransitionInfo.AnimationOptions
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index b46189c..11df331 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -1351,6 +1351,7 @@
assertThat(listener.mImeTargetToken).isEqualTo(imeTarget.mClient.asBinder());
assertThat(listener.mIsRemoved).isFalse();
assertThat(listener.mIsVisibleForImeInputTarget).isTrue();
+ assertThat(listener.mDisplayId).isEqualTo(mDisplayContent.getDisplayId());
imeTarget.mActivityRecord.setVisibleRequested(false);
waitHandlerIdle(mWm.mH);
@@ -1358,11 +1359,13 @@
assertThat(listener.mImeTargetToken).isEqualTo(imeTarget.mClient.asBinder());
assertThat(listener.mIsRemoved).isFalse();
assertThat(listener.mIsVisibleForImeInputTarget).isFalse();
+ assertThat(listener.mDisplayId).isEqualTo(mDisplayContent.getDisplayId());
imeTarget.removeImmediately();
assertThat(listener.mImeTargetToken).isEqualTo(imeTarget.mClient.asBinder());
assertThat(listener.mIsRemoved).isTrue();
assertThat(listener.mIsVisibleForImeInputTarget).isFalse();
+ assertThat(listener.mDisplayId).isEqualTo(mDisplayContent.getDisplayId());
}
@SetupWindows(addWindows = {W_INPUT_METHOD})
@@ -1402,6 +1405,7 @@
assertThat(listener.mImeTargetToken).isEqualTo(client.asBinder());
assertThat(listener.mIsRemoved).isFalse();
assertThat(listener.mIsVisibleForImeTargetOverlay).isTrue();
+ assertThat(listener.mDisplayId).isEqualTo(mDisplayContent.getDisplayId());
// Scenario 2: test relayoutWindow to let the Ime layering target overlay window invisible.
mWm.relayoutWindow(session, client, params, 100, 200, View.GONE, 0, 0, 0,
@@ -1412,6 +1416,7 @@
assertThat(listener.mImeTargetToken).isEqualTo(client.asBinder());
assertThat(listener.mIsRemoved).isFalse();
assertThat(listener.mIsVisibleForImeTargetOverlay).isFalse();
+ assertThat(listener.mDisplayId).isEqualTo(mDisplayContent.getDisplayId());
// Scenario 3: test removeWindow to remove the Ime layering target overlay window.
mWm.removeClientToken(session, client.asBinder());
@@ -1420,6 +1425,7 @@
assertThat(listener.mImeTargetToken).isEqualTo(client.asBinder());
assertThat(listener.mIsRemoved).isTrue();
assertThat(listener.mIsVisibleForImeTargetOverlay).isFalse();
+ assertThat(listener.mDisplayId).isEqualTo(mDisplayContent.getDisplayId());
}
@Test
@@ -1468,22 +1474,25 @@
private boolean mIsRemoved;
private boolean mIsVisibleForImeTargetOverlay;
private boolean mIsVisibleForImeInputTarget;
+ private int mDisplayId;
@Override
public void onImeTargetOverlayVisibilityChanged(IBinder overlayWindowToken,
@WindowManager.LayoutParams.WindowType int windowType, boolean visible,
- boolean removed) {
+ boolean removed, int displayId) {
mImeTargetToken = overlayWindowToken;
mIsVisibleForImeTargetOverlay = visible;
mIsRemoved = removed;
+ mDisplayId = displayId;
}
@Override
public void onImeInputTargetVisibilityChanged(IBinder imeInputTarget,
- boolean visibleRequested, boolean removed) {
+ boolean visibleRequested, boolean removed, int displayId) {
mImeTargetToken = imeInputTarget;
mIsVisibleForImeInputTarget = visibleRequested;
mIsRemoved = removed;
+ mDisplayId = displayId;
}
}
}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 1404413..6c1e1a4 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -80,9 +80,9 @@
import android.provider.Settings;
import android.service.usb.UsbDeviceManagerProto;
import android.service.usb.UsbHandlerProto;
+import android.text.TextUtils;
import android.util.Pair;
import android.util.Slog;
-import android.text.TextUtils;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
@@ -880,7 +880,7 @@
}
}
- private void notifyAccessoryModeExit(int operationId) {
+ protected void notifyAccessoryModeExit(int operationId) {
// make sure accessory mode is off
// and restore default functions
Slog.d(TAG, "exited USB accessory mode");
@@ -2313,8 +2313,13 @@
*/
operationId = sUsbOperationCount.incrementAndGet();
if (msg.arg1 != 1) {
- // Set this since default function may be selected from Developer options
- setEnabledFunctions(mScreenUnlockedFunctions, false, operationId);
+ if (mCurrentFunctions == UsbManager.FUNCTION_ACCESSORY) {
+ notifyAccessoryModeExit(operationId);
+ } else {
+ // Set this since default function may be selected from Developer
+ // options
+ setEnabledFunctions(mScreenUnlockedFunctions, false, operationId);
+ }
}
break;
case MSG_GADGET_HAL_REGISTERED:
diff --git a/telecomm/java/android/telecom/CallerInfoAsyncQuery.java b/telecomm/java/android/telecom/CallerInfoAsyncQuery.java
index 93cd291..a03d7e2 100644
--- a/telecomm/java/android/telecom/CallerInfoAsyncQuery.java
+++ b/telecomm/java/android/telecom/CallerInfoAsyncQuery.java
@@ -483,18 +483,28 @@
// check to see if these are recognized numbers, and use shortcuts if we can.
TelephonyManager tm = context.getSystemService(TelephonyManager.class);
+
boolean isEmergencyNumber = false;
try {
isEmergencyNumber = tm.isEmergencyNumber(number);
- } catch (IllegalStateException ise) {
+ } catch (IllegalStateException | UnsupportedOperationException ise) {
// Ignore the exception that Telephony is not up. Use PhoneNumberUtils API now.
// Ideally the PhoneNumberUtils API needs to be removed once the
// telphony service not up issue can be fixed (b/187412989)
+ // UnsupportedOperationException: telephony.calling may not be supported on this device
isEmergencyNumber = PhoneNumberUtils.isLocalEmergencyNumber(context, number);
}
+
+ boolean isVoicemailNumber;
+ try {
+ isVoicemailNumber = PhoneNumberUtils.isVoiceMailNumber(context, subId, number);
+ } catch (UnsupportedOperationException ex) {
+ isVoicemailNumber = false;
+ }
+
if (isEmergencyNumber) {
cw.event = EVENT_EMERGENCY_NUMBER;
- } else if (PhoneNumberUtils.isVoiceMailNumber(context, subId, number)) {
+ } else if (isVoicemailNumber) {
cw.event = EVENT_VOICEMAIL_NUMBER;
} else {
cw.event = EVENT_NEW_QUERY;
diff --git a/telephony/common/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java
index 94d4d22..9b83719 100644
--- a/telephony/common/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/common/com/android/internal/telephony/SmsApplication.java
@@ -528,7 +528,7 @@
// current SMS app will already be the preferred activity - but checking whether or
// not this is true is just as expensive as reconfiguring the preferred activity so
// we just reconfigure every time.
- defaultSmsAppChanged(context);
+ grantPermissionsToSystemApps(context);
}
}
if (DEBUG_MULTIUSER) {
@@ -542,9 +542,9 @@
}
/**
- * Grants various permissions and appops on sms app change
+ * Grants various permissions and appops, e.g. on sms app change
*/
- private static void defaultSmsAppChanged(Context context) {
+ public static void grantPermissionsToSystemApps(Context context) {
PackageManager packageManager = context.getPackageManager();
AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
@@ -680,7 +680,7 @@
return;
}
- defaultSmsAppChanged(context);
+ grantPermissionsToSystemApps(context);
}
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 0468f48..b9a001d 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -51,6 +51,7 @@
import android.telephony.ims.RcsUceAdapter;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.feature.RcsFeature;
+import android.telephony.satellite.SatelliteManager;
import com.android.internal.telephony.ICarrierConfigLoader;
import com.android.internal.telephony.flags.Flags;
@@ -9603,9 +9604,8 @@
* Defines the rules for data setup retry.
*
* The syntax of the retry rule:
- * 1. Retry based on {@link NetworkCapabilities}. Note that only APN-type network capabilities
- * are supported. If the capabilities are not specified, then the retry rule only applies
- * to the current failed APN used in setup data call request.
+ * 1. Retry based on {@link NetworkCapabilities}. If the capabilities are not specified, then
+ * the retry rule only applies to the current failed APN used in setup data call request.
* "capabilities=[netCaps1|netCaps2|...], [retry_interval=n1|n2|n3|n4...], [maximum_retries=n]"
*
* 2. Retry based on {@link DataFailCause}
@@ -10022,6 +10022,22 @@
"carrier_roaming_ntn_connect_type_int";
/**
+ * Indicates carrier roaming non-terrestrial network emergency call handover type that the
+ * device will use to perform a handover between ESOS or T911.
+ * If this key is set to {@link SatelliteManager#EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS}
+ * then the handover will be made to ESOS. If this key is set to
+ * {@link SatelliteManager#EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911} then the handover
+ * will be made to T911.
+ *
+ * The default value is {@link SatelliteManager#EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911}.
+ *
+ */
+ @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+ public static final String
+ KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT =
+ "carrier_roaming_ntn_emergency_call_to_satellite_handover_type_int";
+
+ /**
* The carrier roaming non-terrestrial network hysteresis time in seconds.
*
* If the device supports P2P satellite messaging which is defined by
@@ -10038,6 +10054,19 @@
"carrier_supported_satellite_notification_hysteresis_sec_int";
/**
+ * An integer key holds the timeout duration in seconds used to determine whether to exit
+ * carrier-roaming NB-IOT satellite mode.
+ *
+ * The timer is started when the device screen is turned off during a satellite session.
+ * When the timer expires, the device exits Carrier Roaming NB IOT NTN.
+ *
+ * The default value is 30 seconds.
+ */
+ @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+ public static final String KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT =
+ "satellite_screen_off_inactivity_timeout_duration_sec_int";
+
+ /**
* Indicating whether DUN APN should be disabled when the device is roaming. In that case,
* the default APN (i.e. internet) will be used for tethering.
*
@@ -11196,7 +11225,10 @@
(int) TimeUnit.SECONDS.toMillis(30));
sDefaults.putBoolean(KEY_SATELLITE_ESOS_SUPPORTED_BOOL, false);
sDefaults.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, 0);
+ sDefaults.putInt(KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT,
+ SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911);
sDefaults.putInt(KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT, 180);
+ sDefaults.putInt(KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT, 30);
sDefaults.putString(KEY_DEFAULT_PREFERRED_APN_NAME_STRING, "");
sDefaults.putBoolean(KEY_SUPPORTS_CALL_COMPOSER_BOOL, false);
sDefaults.putBoolean(KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL, false);
diff --git a/telephony/java/android/telephony/satellite/ISatelliteModemStateCallback.aidl b/telephony/java/android/telephony/satellite/ISatelliteModemStateCallback.aidl
index 9ff73e2..66a20ae 100644
--- a/telephony/java/android/telephony/satellite/ISatelliteModemStateCallback.aidl
+++ b/telephony/java/android/telephony/satellite/ISatelliteModemStateCallback.aidl
@@ -27,4 +27,11 @@
* @param state The current satellite modem state.
*/
void onSatelliteModemStateChanged(in int state);
+
+ /**
+ * Indicates that the satellite emergency mode has changed.
+ *
+ * @param isEmergency True means satellite enabled for emergency mode, false otherwise.
+ */
+ void onEmergencyModeChanged(in boolean isEmergency);
}
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index 4b83b65..0bd9270 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -1531,6 +1531,12 @@
executor.execute(() -> Binder.withCleanCallingIdentity(() ->
callback.onSatelliteModemStateChanged(state)));
}
+
+ @Override
+ public void onEmergencyModeChanged(boolean isEmergency) {
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onEmergencyModeChanged(isEmergency)));
+ }
};
sSatelliteModemStateCallbackMap.put(callback, internalCallback);
return telephony.registerForSatelliteModemStateChanged(mSubId, internalCallback);
diff --git a/telephony/java/android/telephony/satellite/SatelliteModemStateCallback.java b/telephony/java/android/telephony/satellite/SatelliteModemStateCallback.java
index 8d33c88..423a785 100644
--- a/telephony/java/android/telephony/satellite/SatelliteModemStateCallback.java
+++ b/telephony/java/android/telephony/satellite/SatelliteModemStateCallback.java
@@ -35,4 +35,14 @@
*/
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
void onSatelliteModemStateChanged(@SatelliteManager.SatelliteModemState int state);
+
+ /**
+ * Called when the satellite emergency mode has changed.
+ *
+ * @param isEmergency {@code true} enabled for emergency mode, {@code false} otherwise.
+ *
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+ default void onEmergencyModeChanged(boolean isEmergency) {};
}
diff --git a/tests/FlickerTests/AppLaunch/OWNERS b/tests/FlickerTests/AppLaunch/OWNERS
index 2c414a2..d16b57d 100644
--- a/tests/FlickerTests/AppLaunch/OWNERS
+++ b/tests/FlickerTests/AppLaunch/OWNERS
@@ -1,4 +1,2 @@
-# System UI > ... > Overview (recent apps) > UI
-# Bug template url: https://b.corp.google.com/issues/new?component=807991&template=1390280 = per-file *Overview*
# window manager > animations/transitions
# Bug template url: https://b.corp.google.com/issues/new?component=316275&template=1018192
diff --git a/tests/Input/src/com/android/test/input/InputEventAssignerTest.kt b/tests/Input/src/com/android/test/input/InputEventAssignerTest.kt
index c1a86b3..015e188 100644
--- a/tests/Input/src/com/android/test/input/InputEventAssignerTest.kt
+++ b/tests/Input/src/com/android/test/input/InputEventAssignerTest.kt
@@ -18,12 +18,20 @@
import android.view.InputDevice.SOURCE_MOUSE
import android.view.InputDevice.SOURCE_TOUCHSCREEN
+import android.view.InputDevice.SOURCE_STYLUS
+import android.view.InputDevice.SOURCE_TOUCHPAD
+
import android.view.InputEventAssigner
import android.view.KeyEvent
import android.view.MotionEvent
import org.junit.Assert.assertEquals
import org.junit.Test
+sealed class StreamEvent
+private data object Vsync : StreamEvent()
+data class MotionEventData(val action: Int, val source: Int, val id: Int, val expectedId: Int) :
+ StreamEvent()
+
/**
* Create a MotionEvent with the provided action, eventTime, and source
*/
@@ -49,64 +57,164 @@
return KeyEvent(eventTime, eventTime, action, code, repeat)
}
+/**
+ * Check that the correct eventIds are assigned in a stream. The stream consists of motion
+ * events or vsync (processed frame)
+ * Each streamEvent should have unique ids when writing tests
+ * The test passes even if two events get assigned the same eventId, since the mapping is
+ * streamEventId -> motionEventId and streamEvents have unique ids
+ */
+private fun checkEventStream(vararg streamEvents: StreamEvent) {
+ val assigner = InputEventAssigner()
+ var eventTime = 10L
+ // Maps MotionEventData.id to MotionEvent.id
+ // We can't control the event id of the generated motion events but for testing it's easier
+ // to label the events with a custom id for readability
+ val eventIdMap: HashMap<Int, Int> = HashMap()
+ for (streamEvent in streamEvents) {
+ when (streamEvent) {
+ is MotionEventData -> {
+ val event = createMotionEvent(streamEvent.action, eventTime, streamEvent.source)
+ eventIdMap[streamEvent.id] = event.id
+ val eventId = assigner.processEvent(event)
+ assertEquals(eventIdMap[streamEvent.expectedId], eventId)
+ }
+ is Vsync -> assigner.notifyFrameProcessed()
+ }
+ eventTime += 1
+ }
+}
+
class InputEventAssignerTest {
companion object {
private const val TAG = "InputEventAssignerTest"
}
/**
- * A single MOVE event should be assigned to the next available frame.
+ * A single event should be assigned to the next available frame.
*/
@Test
- fun testTouchGesture() {
- val assigner = InputEventAssigner()
- val event = createMotionEvent(MotionEvent.ACTION_MOVE, 10, SOURCE_TOUCHSCREEN)
- val eventId = assigner.processEvent(event)
- assertEquals(event.id, eventId)
+ fun testTouchMove() {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_MOVE, SOURCE_TOUCHSCREEN, id = 1, expectedId = 1)
+ )
+ }
+
+ @Test
+ fun testMouseMove() {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_MOVE, SOURCE_MOUSE, id = 1, expectedId = 1)
+ )
+ }
+
+ @Test
+ fun testMouseScroll() {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_SCROLL, SOURCE_MOUSE, id = 1, expectedId = 1)
+ )
+ }
+
+ @Test
+ fun testStylusMove() {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_MOVE, SOURCE_STYLUS, id = 1, expectedId = 1)
+ )
+ }
+
+ @Test
+ fun testStylusHover() {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_HOVER_MOVE, SOURCE_STYLUS, id = 1, expectedId = 1)
+ )
+ }
+
+ @Test
+ fun testTouchpadMove() {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_MOVE, SOURCE_STYLUS, id = 1, expectedId = 1)
+ )
}
/**
- * DOWN event should be used until a vsync comes in. After vsync, the latest event should be
- * produced.
+ * Test that before a VSYNC the event id generated by input event assigner for move events is
+ * the id of the down event. Move events coming after a VSYNC should be assigned their own event
+ * id
*/
- @Test
- fun testTouchDownWithMove() {
- val assigner = InputEventAssigner()
- val down = createMotionEvent(MotionEvent.ACTION_DOWN, 10, SOURCE_TOUCHSCREEN)
- val move1 = createMotionEvent(MotionEvent.ACTION_MOVE, 12, SOURCE_TOUCHSCREEN)
- val move2 = createMotionEvent(MotionEvent.ACTION_MOVE, 13, SOURCE_TOUCHSCREEN)
- val move3 = createMotionEvent(MotionEvent.ACTION_MOVE, 14, SOURCE_TOUCHSCREEN)
- val move4 = createMotionEvent(MotionEvent.ACTION_MOVE, 15, SOURCE_TOUCHSCREEN)
- var eventId = assigner.processEvent(down)
- assertEquals(down.id, eventId)
- eventId = assigner.processEvent(move1)
- assertEquals(down.id, eventId)
- eventId = assigner.processEvent(move2)
- // Even though we already had 2 move events, there was no choreographer callback yet.
- // Therefore, we should still get the id of the down event
- assertEquals(down.id, eventId)
+ private fun testDownAndMove(source: Int) {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_DOWN, source, id = 1, expectedId = 1),
+ MotionEventData(MotionEvent.ACTION_MOVE, source, id = 2, expectedId = 1),
+ Vsync,
+ MotionEventData(MotionEvent.ACTION_MOVE, source, id = 4, expectedId = 4)
+ )
+ }
- // Now send CALLBACK_INPUT to the assigner. It should provide the latest motion event
- assigner.notifyFrameProcessed()
- eventId = assigner.processEvent(move3)
- assertEquals(move3.id, eventId)
- eventId = assigner.processEvent(move4)
- assertEquals(move4.id, eventId)
+ @Test
+ fun testTouchDownAndMove() {
+ testDownAndMove(SOURCE_TOUCHSCREEN)
+ }
+
+ @Test
+ fun testMouseDownAndMove() {
+ testDownAndMove(SOURCE_MOUSE)
+ }
+
+ @Test
+ fun testStylusDownAndMove() {
+ testDownAndMove(SOURCE_STYLUS)
+ }
+
+ @Test
+ fun testTouchpadDownAndMove() {
+ testDownAndMove(SOURCE_TOUCHPAD)
}
/**
- * Similar to the above test, but with SOURCE_MOUSE. Since we don't have down latency
- * concept for non-touchscreens, the latest input event will be used.
+ * After an up event, motion events should be assigned their own event id
*/
@Test
- fun testMouseDownWithMove() {
- val assigner = InputEventAssigner()
- val down = createMotionEvent(MotionEvent.ACTION_DOWN, 10, SOURCE_MOUSE)
- val move1 = createMotionEvent(MotionEvent.ACTION_MOVE, 12, SOURCE_MOUSE)
- var eventId = assigner.processEvent(down)
- assertEquals(down.id, eventId)
- eventId = assigner.processEvent(move1)
- assertEquals(move1.id, eventId)
+ fun testMouseDownUpAndScroll() {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_DOWN, SOURCE_MOUSE, id = 1, expectedId = 1),
+ MotionEventData(MotionEvent.ACTION_UP, SOURCE_MOUSE, id = 2, expectedId = 2),
+ MotionEventData(MotionEvent.ACTION_SCROLL, SOURCE_MOUSE, id = 3, expectedId = 3)
+ )
+ }
+
+ /**
+ * After an up event, motion events should be assigned their own event id
+ */
+ @Test
+ fun testStylusDownUpAndHover() {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_DOWN, SOURCE_STYLUS, id = 1, expectedId = 1),
+ MotionEventData(MotionEvent.ACTION_UP, SOURCE_STYLUS, id = 2, expectedId = 2),
+ MotionEventData(MotionEvent.ACTION_HOVER_ENTER, SOURCE_STYLUS, id = 3, expectedId = 3)
+ )
+ }
+
+ /**
+ * After a cancel event, motion events should be assigned their own event id
+ */
+ @Test
+ fun testMouseDownCancelAndScroll() {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_DOWN, SOURCE_MOUSE, id = 1, expectedId = 1),
+ MotionEventData(MotionEvent.ACTION_CANCEL, SOURCE_MOUSE, id = 2, expectedId = 2),
+ MotionEventData(MotionEvent.ACTION_SCROLL, SOURCE_MOUSE, id = 3, expectedId = 3)
+ )
+ }
+
+ /**
+ * After a cancel event, motion events should be assigned their own event id
+ */
+ @Test
+ fun testStylusDownCancelAndHover() {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_DOWN, SOURCE_STYLUS, id = 1, expectedId = 1),
+ MotionEventData(MotionEvent.ACTION_CANCEL, SOURCE_STYLUS, id = 2, expectedId = 2),
+ MotionEventData(MotionEvent.ACTION_HOVER_ENTER, SOURCE_STYLUS, id = 3, expectedId = 3)
+ )
}
/**
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 45bf8e3..9444dd9 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -107,7 +107,7 @@
Visibility::Level visibility_level = Visibility::Level::kUndefined;
bool staged_api = false;
bool allow_new = false;
- FlagStatus flag_status;
+ FlagStatus flag_status = FlagStatus::NoFlag;
std::optional<OverlayableItem> overlayable_item;
std::optional<StagedId> staged_alias;
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index 9530c17..4f76e7d 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -104,7 +104,7 @@
// The actual Value.
std::unique_ptr<Value> value;
- FlagStatus flag_status;
+ FlagStatus flag_status = FlagStatus::NoFlag;
ResourceConfigValue(const android::ConfigDescription& config, android::StringPiece product)
: config(config), product(product) {
@@ -271,7 +271,7 @@
std::optional<AllowNew> allow_new;
std::optional<StagedId> staged_id;
bool allow_mangled = false;
- FlagStatus flag_status;
+ FlagStatus flag_status = FlagStatus::NoFlag;
};
struct NewResourceBuilder {
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index 67a4828..1942fc11 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -212,7 +212,11 @@
collision_result =
ResolveMergeCollision(override_styles_instead_of_overlaying, dst_value, src_value, pool);
} else {
- collision_result = ResourceTable::ResolveValueCollision(dst_value, src_value);
+ collision_result = ResourceTable::ResolveFlagCollision(dst_config_value->flag_status,
+ src_config_value->flag_status);
+ if (collision_result == CollisionResult::kConflict) {
+ collision_result = ResourceTable::ResolveValueCollision(dst_value, src_value);
+ }
}
if (collision_result == CollisionResult::kConflict) {
@@ -291,6 +295,7 @@
} else {
dst_config_value =
dst_entry->FindOrCreateValue(src_config_value->config, src_config_value->product);
+ dst_config_value->flag_status = src_config_value->flag_status;
}
// Continue if we're taking the new resource.
diff --git a/wifi/java/src/android/net/wifi/WifiBlobStore.java b/wifi/java/src/android/net/wifi/WifiBlobStore.java
index 8737c7e9..57d997b 100644
--- a/wifi/java/src/android/net/wifi/WifiBlobStore.java
+++ b/wifi/java/src/android/net/wifi/WifiBlobStore.java
@@ -16,8 +16,11 @@
package android.net.wifi;
+import android.os.Build;
import android.os.ServiceManager;
+import android.os.SystemProperties;
import android.security.legacykeystore.ILegacyKeystore;
+import android.util.Log;
import com.android.internal.net.ConnectivityBlobStore;
@@ -26,13 +29,44 @@
* @hide
*/
public class WifiBlobStore extends ConnectivityBlobStore {
+ private static final String TAG = "WifiBlobStore";
private static final String DB_NAME = "WifiBlobStore.db";
private static final String LEGACY_KEYSTORE_SERVICE_NAME = "android.security.legacykeystore";
+ private static final boolean sIsVendorApiLevelGreaterThanT = isVendorApiLevelGreaterThanT();
private static WifiBlobStore sInstance;
private WifiBlobStore() {
super(DB_NAME);
}
+ private static boolean isVendorApiLevelGreaterThanT() {
+ int androidT = Build.VERSION_CODES.TIRAMISU; // redefine to avoid errorprone build issue
+ String[] vendorApiLevelProps = {
+ "ro.board.api_level", "ro.board.first_api_level", "ro.vndk.version"};
+ for (String propertyName : vendorApiLevelProps) {
+ int apiLevel = SystemProperties.getInt(propertyName, -1);
+ if (apiLevel != -1) {
+ Log.i(TAG, "Retrieved API level property, value=" + apiLevel);
+ return apiLevel > androidT;
+ }
+ }
+ // If none of the properties are defined, we are using the current API level (> V)
+ Log.i(TAG, "No API level properties are defined");
+ return true;
+ }
+
+ /**
+ * Check whether supplicant can access values stored in WifiBlobstore.
+ *
+ * NonStandardCertCallback was added in Android U, allowing supplicant to access the
+ * WifiKeystore APIs, which access WifiBlobstore. Previously, supplicant used
+ * WifiKeystoreHalConnector to access values stored in Legacy Keystore.
+ *
+ * @hide
+ */
+ public static boolean supplicantCanAccessBlobstore() {
+ return sIsVendorApiLevelGreaterThanT;
+ }
+
/** Returns an instance of WifiBlobStore. */
public static WifiBlobStore getInstance() {
if (sInstance == null) {
diff --git a/wifi/java/src/android/net/wifi/WifiMigration.java b/wifi/java/src/android/net/wifi/WifiMigration.java
index 1a20a12..6ea20ec 100644
--- a/wifi/java/src/android/net/wifi/WifiMigration.java
+++ b/wifi/java/src/android/net/wifi/WifiMigration.java
@@ -574,7 +574,7 @@
*
* @hide
*/
- @FlaggedApi(Flags.FLAG_LEGACY_KEYSTORE_TO_WIFI_BLOBSTORE_MIGRATION)
+ @FlaggedApi(Flags.FLAG_LEGACY_KEYSTORE_TO_WIFI_BLOBSTORE_MIGRATION_READ_ONLY)
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static void migrateLegacyKeystoreToWifiBlobstore() {
final long identity = Binder.clearCallingIdentity();
diff --git a/wifi/wifi.aconfig b/wifi/wifi.aconfig
index 5a214b7..90d13e6 100644
--- a/wifi/wifi.aconfig
+++ b/wifi/wifi.aconfig
@@ -19,11 +19,12 @@
}
flag {
- name: "legacy_keystore_to_wifi_blobstore_migration"
+ name: "legacy_keystore_to_wifi_blobstore_migration_read_only"
is_exported: true
namespace: "wifi"
description: "Add API to migrate all values from Legacy Keystore to the new Wifi Blobstore database"
bug: "332560152"
+ is_fixed_read_only: true
}
flag {